2016-02-29 160 views
12

按我的理解ArrayList,默认容量为10,当它增长超过10,这将创造新的能力等新的对象..为什么每次添加新元素时,ArrayList的hashCode()都会发生变化?

所以出于好奇,我输入下面的程序来检查hashcode()ArrayList对象:

public class TestCoreJava { 

    public static void main(String [] args){ 

     ArrayList al = new ArrayList(); 

     for(int i=0;i<15;i++){ 

      al.add("Temp"+i); 
      System.out.println("Hashcode for "+i+" element "+al.hashCode()); 
     } 
    } 
} 

根据上述情况,当我不ArrayList设置初始容量默认是10 因此而增加11要素,它会创建一个新的对象,并增加容量ArrayList

当我打印ArrayList对象的哈希码时,它每次都给出一个新的hashcode()

以下是O/P:

Hashcode for 0 element 80692955 
Hashcode for 1 element -1712792766 
Hashcode for 2 element -1476275268 
Hashcode for 3 element 1560799875 
Hashcode for 4 element 1220848797 
Hashcode for 5 element -727700028 
Hashcode for 6 element -1003171458 
Hashcode for 7 element -952851195 
Hashcode for 8 element 607076959 
Hashcode for 9 element 1720209478 
Hashcode for 10 element -6600307 
Hashcode for 11 element -1998096089 
Hashcode for 12 element 690044110 
Hashcode for 13 element -1876955640 
Hashcode for 14 element 150430735 

据默认容量的概念,直到10元,因为没有新的对象需要,直到这一点要创建它应该印有相同hashcode(),但它是不是这样。

+0

'的hashCode()'绑定到'这表明,(如果你看看源代码,他们这样做)2列出了不同的元素,但相同的容量应该返回不同的散列码的equals()' – Thomas

+0

的可能的复制[在Java中重写equals和hashCode时应考虑哪些问题?](http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in- java) – Raedwald

回答

32

的的ArrayListhashCodehashCode小号存储在ArrayList的所有元件中的功能,所以当容量的变化,它的变化当添加或删除元素或突变的元件中的一个它不改变以一种改变其hashCode的方式。

这里是在Java 8实现(它在AbstractList实际执行):

public int hashCode() { 
    int hashCode = 1; 
    for (E e : this) 
     hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); 
    return hashCode; 
} 

顺便说一句,这是出现在的List接口hashCode()的Javadoc确切的代码:

int java.util.List.hashCode()

返回哈希代码值为这个清单。列表的哈希码被定义为以下计算的结果:

int hashCode = 1; 
for (E e : list) 
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); 
+0

谢谢Eran指点我正确的答案:) – suyash

4

ListhashCode实现是defined in terms of the hashCode of it's elements。这意味着对于ArrayList是符合List的实施,它的hashCode必须在其内容更改时发生更改。

更一般地说:对于可变对象,hashCode应该随时更改,以使它们不会变为其先前状态。

您似乎认为它使用Objectdefault hashCode,但情况并非如此。

此外,即使ArrayList没有实施hashCode,一个ArrayList默认的哈希码(又称identity hash code)将不会改变,如果内部数组被重新分配,为ArrayList对象本身保持不变,只是内部数组对象(您无法直接访问)将被替换为新的对象。

2

对此的解释可以通过查看the docs for hashCode

发现如果两个对象根据equals(Object)方法是相等的,则调用每个两个对象的哈希码方法必须产生相同的整数结果。

ArrayList的内容发生变化时,它也会改变其他对象的相同位置。为了履行Object的这部分合同,ArrayList或者需要在hashCode内容变化时更改,或者每个ArrayList具有相同的hashCode。为了使其有用,他们显然选择了前者。这可以通过查看List's docs进行验证。

返回此列表的哈希码值。列表的散列码 定义为以下计算的结果:

int hashCode = 1; 
for (E e : list) 
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); 

这确保list1.equals(列表2)意味着 实现list1.hashCode()== list2.hashCode(),用于任何两个列表,列表1和列表2, 按照Object.hashCode()的一般合约的要求。