2016-02-29 72 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()的一般合約的要求。

相關問題