这很奇怪。一位同事询问了java中myArray.hashCode()的实现。我以为我知道,但后来我做了一些测试。检查下面的代码。我注意到的奇怪的想法是,当我写出第一个系统时,结果是不同的。请注意,它几乎就像报告内存地址并修改类移动了地址或其他内容。只是想我会分享。
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)));
答案 0 :(得分:88)
java.lang.Array
hashCode
方法继承自Object
,这意味着哈希码取决于引用。要根据数组的内容获取哈希码,请使用Arrays.hashCode
。
请注意它的浅层哈希码实现。深度实施也存在Arrays.deepHashCode
。
答案 1 :(得分:4)
数组使用默认的哈希码,它基于内存位置(但它不一定是 内存位置,因为它只是int
而且所有内存地址都不会适合)。您也可以通过打印System.identityHashCode(foo)
的结果来看到这一点。
如果数组相同,则只有equal
数组。因此,数组哈希码通常只有相同,相同的数组。
答案 2 :(得分:2)
Object.hashCode()的默认实现确实是返回对象的指针值,尽管这取决于实现。例如,64位JVM可以将指针和XOR以及高位和低位字组合在一起。如果有意义,则鼓励子类覆盖此行为。
但是,对可变数组执行相等比较没有意义。如果元素发生变化,则两者不再相等。为了保持相同数组始终返回相同hashCode的不变量,无论其元素发生什么,数组都不会覆盖默认的hashcode行为。
请注意,java.util.Arrays提供了一个deepHashCode()实现,用于基于数组内容进行散列,而不是数组本身的标识,这很重要。
答案 3 :(得分:2)
我同意使用java.util.Arrays.hashCode(或google guava通用包装器Objects.hashcode),但请注意,如果您使用Terracotta,这可能会导致问题 - 请参阅this link