À la longueur d'une Chaîne de la clé d'un HashMap considéré comme une mauvaise pratique?
J'essaie de prêter attention à de bonnes performances et un code propre tout le temps.
Je vais avoir des difficultés en essayant de comprendre si il est sain d'avoir une table de hachage avec des touches de 150 caractères.
- Est-il une loi non écrite de la longueur de la table de hachage de la clé?
- Est-il considéré comme une mauvaise pratique d'avoir des clés de Chaîne, disons 150 caractères?
- - T-il sur les performances? À quelle longueur?
- Chaque opération d'acquisition est forcément linéaire en la longueur de la clé. Je pense que c'est la seule préoccupation qui doit prendre en compte. Cela ne signifie pas encore que la 15-char clés seront 10 fois plus rapide à consulter.
Vous devez vous connecter pour publier un commentaire.
Pas vraiment, 150 caractères Chaîne de caractères est relativement simple de calculer un
hashCode
pour.Cela étant dit, dans des circonstances comme cela, je vous conseille de le tester!
Créer une routine qui remplit une table de hachage avec, disons, insérer une taille ici qui est représentatif de votre scénario d'utilisation valeurs aléatoires avec 5 chaînes de caractères comme des clés. Mesurer combien de temps cela prend. Puis faire de même pour 15 touches de caractères, et de voir comment il évolue.
Aussi, des Chaînes de caractères en Java sont immuables, ce qui signifie que
hashCode
peut être mis en cache pour chaque Chaîne est stockée dans la Chaîne de caractères Constante de la Piscine, et n'a pas besoin d'être recalculées lorsque vous appelez hashCode sur le même objet de type String.Cela signifie que même si vous êtes calcul plus des codes de hachage lors de la création de votre carte, sur l'accès à beaucoup de ceux qui seront déjà pré-calculés et mis en cache, faisant de la taille de la Chaîne d'origine, même les moins pertinentes.
String.hashCode
mise en cache sur le premier calcul, sans rapport avec la piscine. Le calcul en lui-même prend de 4 cycles par char, qui est 4 fois plus que l'optimum. 2. En raison de cette mise en cache, la méthode equals sera probablement dominer le temps.Si il y est, il est également non-dits. Je mesure votre cas d'utilisation dans un profiler et seulement s'inquiéter au sujet de choses que vous pouvez mesurer comme un problème, pas les choses que vous pouvez imaginer peut-être un problème.
J'en doute.
Tout ce qui affecte les performances, généralement de petites à la matière, ou parfois même mesure. La question devrait être; avez-vous besoin de 150 touches de caractères. Si vous le faites, alors les utiliser.
Il y a un exotique cas où l'ajout de chaînes de caractères avec hashCode() de zéro est une mauvaise idée. C'est parce que dans Java 1.0 à 6 n'a pas d'optimiser le cas d'utilisation d'un hashCode de zéro et il peut être prévu pour les attaques de déni de service. Java 7 corrige cela en ayant un secondaire, de moins en moins prévisibles hashcode.
Pourquoi ne pas la Chaîne de hashCode() cache de 0?
-XX:+UseCompressedStrings
qui peut utiliser un octet par caractère.HashMap
corrige, pasString
.String#hashCode
est fondamentalement inchangée.int32
est seulement une privé de la méthode d'assistance et de l'ensemble du mécanisme n'est pas une partie de l'API publique, ou même accessible au public.HashMap
et d'autres Java Cadre de Collecte des classes. Quelle que soit la logique que vous avez de votre propre qui s'appuie surObject#hashCode
, vous ne pouvez pas tirer profit de la mise en valeur. C'est quelque chose d'être conscient de.hash32
. Ce qui est normal en raison de l'aide de l'arborescence de poubelles dans le cas de nombreux conflits.Réponse longue: Un rapide coup d'œil au code source de
String::hashCode()
révèle que le hachage est mis en cache après le premier appel. Pendant ce temps,String::equals()
est O(n) si les chaînes sont égaux mais pas identiques (c'est à dire,equals()
est vrai, mais==
est faux parce qu'ils sont affectés à des adresses différentes).De sorte que les effets sur la performance que vous allez voir sont avec:
Passant jamais-avant-haché chaînes dans les appels à
HashMap
fonctions. Cependant, la génération de beaucoup de cordes en sera l'impact sur la performance en elle-même.Appels à
HashMap::get()
etHashMap::put()
à l'aide d'une chaîne de clé, qui est égale à déjà une clé dans la table de hachage (parce que si la clé n'est pas dans la collection, puis probablement hashCode() sera appelée. Mais si elle l'est, equals() permettra de comparer tous les caractères jusqu'à ce qu'il détermine les chaînes sont égales). Mais seulement si les chaînes transmises à ces fonctions ne sont pas les mêmes objets qui sont déjà dans la table de hachage, parce que dans ce casequals()
est très rapide.En outre, les littéraux de chaîne, chaîne de constantes, et manuellement
intern()
'd les chaînes de rejoindre la Chaîne de caractères Constante de la Piscine, dans laquelle tous "égaux" les chaînes sont le même objet avec la même adresse. Donc, si vous travaillez exclusivement avec ces chaînes,hashCode
etequals
sont très rapides.Bien sûr, l'impact de la performance ne sera pas du tout perceptible, sauf si vous êtes en train de faire les opérations ci-dessus dans une boucle serrée (parce que 150 caractères n'est pas long et hashCode() et equals() sont à la fois efficace).
Réponse courte: de Référence.
Tout d'abord, il n'y a pas de "règle non écrite". Si de longues chaînes de caractères comme des touches de sens à partir d'un point de vue algorithmique, les utiliser. Si le profilage indique qu'il y a un problème, alors vous optimiser.
Alors, comment peut de longues chaînes d'affecter les performances de la table de hachage?
Long des chaînes de prendre plus de mémoire que le court, et que pourrait entraîner, de façon mesurable, plus la collecte des ordures fois, et d'autres secondaires effets sur les performances liées à la mémoire matérielle des caches, Tlb et (éventuellement) de la mémoire physique de la page de contention.
Le hashcode algorithme pour la Chaîne utilise tous les caractères de la chaîne et donc son coût est proportionnel à la longueur de la chaîne. Ceci est atténué par le fait que la Chaîne de hashcodes sont mis en cache. (Le 2e et le moment ultérieur que vous appelez
hashcode
sur une Chaîne, vous obtenez la valeur mise en cache.) Cependant, que seulement une aide (ici) si vous n'multiples de la table de hachage des opérations ayant le même objet String comme une clé.Lorsque vous obtenez un hash collision, la table de hachage tombe en arrière à l'aide
String.equals()
pour comparer des clés lors de la recherche sélectionnés de hachage de la chaîne. Dans le pire des cas (par exemple lorsque les chaînes sontequal
mais pas==
),String.equals()
implique de comparer tous les caractères des 2 chaînes.Comme vous pouvez le voir, ces effets seront spécifiques à l'application, et par conséquent, ils sont difficiles à prédire. Par conséquent, à une "règle" est peu susceptible d'être utile.