Java Array HashCode实现

这很奇怪 一位同事询问了java中myArray.hashCode()的实现。 我以为我知道,但后来我跑了一些testing。 检查下面的代码。 我注意到奇怪的是,当我写第一个系统的结果是不同的。 请注意,这几乎就像是报告内存地址,并修改类地址或东西。 只是想我会分享。

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))); 

java.lang.Array hashCode方法从Objectinheritance,这意味着哈希码依赖于引用。 要获取基于数组内容的哈希码,请使用Arrays.hashCode

注意,虽然它是一个浅的哈希码实现。 深度实现也是Arrays.deepHashCode

数组使用默认的哈希码,这是基于内存位置(但不一定内存位置,因为它只是一个int ,所有的内存地址将不适合)。 您也可以通过打印System.identityHashCode(foo)的结果来看到这一点。

数组只有相同,相同的数组才是equal 。 所以,一般来说,如果数组散列码相同,数组相同,那么数组散列码也是相同的。

Object.hashCode()的默认实现确实是返回对象的指针值,尽pipe这是依赖于实现的。 例如,一个64位的JVM可能会把指针和XOR以及高位和低位字连在一起。 如果有意义的话,鼓励子类覆盖这种行为。

但是,对可变数组执行相等比较没有任何意义。 如果一个元素发生了变化,那么两者不再相同。 为了保持不变,相同的数组总是返回相同的hashCode,而不pipe它的元素发生了什么,数组不会覆盖默认的hashcode行为。

请注意,java.util.Arrays提供了一个deepHashCode()实现,用于根据数组内容而不是数组本身的标识进行散列,这一点非常重要。

我同意使用java.util.Arrays.hashCode(或谷歌guava通用包装Objects.hashcode),但请注意,这可能会导致问题,如果您使用兵马俑 – 请参阅此链接