La valeur hashCode d'une chaîne Java est calculée comme suit (String.hashCode () ):
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
Existe-t-il des circonstances (par exemple, la version JVM, le fournisseur, etc.) dans lesquelles l'expression suivante sera évaluée à false?
boolean expression = "This is a Java string".hashCode() == 586653468
Mise à jour n ° 1: Si vous prétendez que la réponse est "oui, il y a de telles circonstances" - alors veuillez donner un exemple concret de quand "Ceci est une chaîne Java" .hashCode ()! = 586653468. Essayez d'être aussi spécifique / concret que possible.
Mise à jour # 2: Nous savons tous que se fier aux détails d'implémentation de hashCode () est mauvais en général. Cependant, je parle spécifiquement de String.hashCode () - veuillez donc garder la réponse concentrée sur String.hashCode (). Object.hashCode () est totalement hors de propos dans le contexte de cette question.
Réponses:
Je peux voir cette documentation aussi loin que Java 1.2.
S'il est vrai qu'en général, vous ne devriez pas compter sur une implémentation de code de hachage qui reste la même, c'est maintenant un comportement documenté pour
java.lang.String
, donc le changer compterait comme la rupture des contrats existants.Dans la mesure du possible, vous ne devriez pas vous fier à ce que les codes de hachage restent les mêmes d'une version à l'autre, etc. - mais dans mon esprit,
java.lang.String
c'est un cas spécial simplement parce que l'algorithme a été spécifié ... tant que vous êtes prêt à abandonner la compatibilité avec les versions antérieures à la l'algorithme a été spécifié, bien sûr.la source
J'ai trouvé quelque chose à propos de JDK 1.0 et 1.1 et> = 1.2:
Quelque chose de différent, car vous semblez avoir besoin d'un numéro: que diriez-vous d'utiliser CRC32 ou MD5 au lieu du hashcode et vous êtes prêt à partir - pas de discussions et pas de soucis du tout ...
la source
Vous ne devez pas vous fier à un code de hachage égal à une valeur spécifique. Juste qu'il renverra des résultats cohérents dans la même exécution. La documentation de l'API dit ce qui suit:
EDIT Puisque le javadoc pour String.hashCode () spécifie comment le code de hachage d'un String est calculé, toute violation de ceci violerait la spécification de l'API publique.
la source
Comme indiqué ci-dessus, en général, vous ne devez pas vous fier au code de hachage d'une classe qui reste le même. Notez que même les exécutions ultérieures du même application sur la même machine virtuelle peuvent produire des valeurs de hachage différentes. AFAIK la fonction de hachage de Sun JVM calcule le même hachage à chaque exécution, mais ce n'est pas garanti.
Notez que ce n'est pas théorique. La fonction de hachage pour java.lang.String a été modifiée dans JDK1.2 (l'ancien hachage avait des problèmes avec les chaînes hiérarchiques comme les URL ou les noms de fichiers, car il avait tendance à produire le même hachage pour les chaînes qui ne différaient qu'à la fin).
java.lang.String est un cas particulier, car l'algorithme de son hashCode () est (maintenant) documenté, vous pouvez donc probablement vous y fier. Je considère toujours que c'est une mauvaise pratique. Si vous avez besoin d'un algorithme de hachage avec des propriétés spéciales et documentées, écrivez-en un :-).
la source
Un autre (!) Problème à craindre est le changement possible d'implémentation entre les versions antérieures / tardives de Java. Je ne pense pas que les détails d'implémentation soient gravés dans la pierre, et donc potentiellement une mise à niveau vers une future version Java pourrait causer des problèmes.
En bout de ligne, je ne compterais pas sur la mise en œuvre de
hashCode()
.Vous pouvez peut-être mettre en évidence le problème que vous essayez réellement de résoudre en utilisant ce mécanisme, ce qui mettra en évidence une approche plus appropriée.
la source
switch
instructions sur les chaînes se compilent en code reposant sur un code de hachage fixe particulier, les modifications apportées àString
l'algorithme de code de hachage de 's briseraient définitivement le code existant…Juste pour répondre à votre question et pour ne poursuivre aucune discussion. L'implémentation Apache Harmony JDK semble utiliser un algorithme différent, au moins il semble totalement différent:
Sun JDK
Harmonie Apache
N'hésitez pas à le vérifier vous-même ...
la source
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
sauf si je me trompe, c'est parce qu'Android utilise l'implémentation par Sun de l'objet String sans changement.Si vous vous inquiétez des modifications et éventuellement des machines virtuelles incompatibles, copiez simplement l'implémentation de hashcode existante dans votre propre classe d'utilitaire et utilisez-la pour générer vos hashcodes.
la source
Le hashcode sera calculé en fonction des valeurs ASCII des caractères de la chaîne.
C'est l'implémentation dans la classe String est la suivante
Les collisions dans le hashcode sont inévitables. Par exemple, les chaînes "Ea" et "FB" donnent le même hashcode que 2236
la source