Implémentation Java Array HashCode

C’est étrange. Un collègue a posé des questions sur l’implémentation de myArray.hashCode () dans Java. Je pensais que je le savais mais j’ai passé quelques tests. Vérifiez le code ci-dessous. Je trouve étrange que lorsque j’ai écrit les premiers résultats, les résultats étaient différents. Notez que c’est presque comme s’il s’agissait de signaler une adresse mémoire et de modifier la classe déplacé l’adresse ou quelque chose. Je pensais juste que je partagerais.

int[] foo = new int[100000]; java.util.Random rand = new java.util.Random(); for(int a = 0; a < foo.length; a++) foo[a] = rand.nextInt(); int[] bar = new int[100000]; int[] baz = new int[100000]; int[] bax = new int[100000]; for(int a = 0; a < foo.length; a++) bar[a] = baz[a] = bax[a] = foo[a]; System.out.println(foo.hashCode() + " ----- " + bar.hashCode() + " ----- " + baz.hashCode() + " ----- " + bax.hashCode()); // returns 4097744 ----- 328041 ----- 2083945 ----- 2438296 // Consistently unless you modify the class. Very weird // Before adding the comments below it returned this: // 4177328 ----- 4097744 ----- 328041 ----- 2083945 System.out.println("Equal ?? " + (java.util.Arrays.equals(foo, bar) && java.util.Arrays.equals(bar, baz) && java.util.Arrays.equals(baz, bax) && java.util.Arrays.equals(foo, bax))); 

La méthode hashCode java.lang.Array est héritée de Object , ce qui signifie que le hashcode dépend de la référence. Pour obtenir le code de hachage basé sur le contenu du tableau, utilisez Arrays.hashCode .

Méfiez-vous si c’est une implémentation de hashcode peu profonde. Une implémentation approfondie est également présente Arrays.deepHashCode .

Les tableaux utilisent le code de hachage par défaut, qui est basé sur l’emplacement de la mémoire (mais ce n’est pas nécessairement l’ emplacement de la mémoire, car seul un int et toutes les adresses de mémoire ne conviennent pas). Vous pouvez le voir en imprimant également le résultat de System.identityHashCode(foo) .

Les tableaux ne sont equal que s’ils sont identiques, tableau identique. Ainsi, les codes de hachage des tableaux ne seront égaux, en général, que s’ils sont identiques, ils sont identiques.

L’implémentation par défaut de Object.hashCode () consiste en effet à renvoyer la valeur du pointeur de l’object, même si cela dépend de l’implémentation. Par exemple, une JVM 64 bits peut rassembler le pointeur et le XOR et les mots d’ordre supérieur et inférieur. Les sous-classes sont encouragées à remplacer ce comportement si cela est logique.

Cependant, il n’est pas judicieux d’effectuer des comparaisons d’égalité sur des tableaux pouvant être modifiés. Si un élément change, les deux ne sont plus égaux. Pour conserver l’invariant que le même tableau retournera toujours le même hashCode, peu importe ce qu’il advient de ses éléments, les tableaux ne remplacent pas le comportement par défaut du hashcode.

Notez que java.util.Arrays fournit une implémentation deepHashCode () lorsque le hachage basé sur le contenu du tableau, plutôt que sur l’identité du tableau lui-même, est important.

Je suis d’accord avec l’utilisation de java.util.Arrays.hashCode (ou du wrapper générique Objects.hashcode de Google Guava), mais sachez que cela peut causer des problèmes si vous utilisez Terracotta – voir ce lien