2011-08-31 59 views
0

假設我有下面的類。以哈希值爲基礎的對象抽取集合

class S{ 

String txt = null; 

S(String i){ 
txt=i; 
} 

public static void main(String args []){ 
S s1 = new S("a"); 
S s2 = new S("b"); 
S s3 = new S("a"); 

Map m = new HashMap(); 
m.put(s1, "v11"); 
m.put(s2, "v22"); 
m.put(s3, "v33"); 

System.out.println(m.size()); 
} 

//just a plain implementation 
public boolean equals(Object o) 
{ 
     S cc = (S) o; 
     if (this.i.equals(cc.i)) 
     {  
     return true; 
     } 
     else 
     { 
     return false; 
     }  
    } 

    public int hashCode() 
    { 
     return 222; 
    } 

} 

這會在上面運行時返回大小爲2。它完全好。如果我們評論hashCode(),它返回3,這也是正確的。但是如果我們評論equals並保留hashCode,它應該返回2對嗎?相反,它返回3.當把對象放到hashmap map中時,會檢查一個對象的哈希碼,如果它相同,它會將之前的地圖值替換爲新的哈希值。

謝謝。

回答

2

但是,如果我們評論等於並保留hashCode它應該返回2 對不對?相反它返回3.

3項是正確的行爲。 3個對象將被散列到同一個桶中,但是因爲所有3個都不相同,所以這個桶將包含具有相同散列代碼但不相等的值鏈(Java中的HashMap的鏈接列表)。

當把對象HashMap的地圖將檢查對象的哈希碼,如果它同 將地圖的前值替換到右邊新建一個?

如果將它們散列到同一個存儲桶中,這並不意味着一個值將取代另一個值。然後將這些值進行比較以得到平等。如果它們相等,則舊值將被替換,如果它們不是 - 將新值添加到鏈表的尾部(對於該桶)。

1

散列碼僅用於確定放置對象的存儲區。每個桶可以包含多個對象。所以必須實現哈希碼以確保相同的對象進入同一個桶。換句話說,相同的對象必須具有相同的哈希碼,但具有相同哈希碼的對象不一定相等。

1

當你只覆蓋hashcode沒有什麼真正改變。您只需將每個對象與return 222放在同一個存儲桶中即可。所以HashMap效率更低,但其合同不會改變。

0

哈希碼是第一個快速找到兩個對象是否相等的方法。散列容器使用它來決定對象可能在哪個「插槽」中進行檢索,並檢索它而不檢查所有插槽中的所有對象。

如果你的散列碼總是相同的,那麼所有的對象將被定向到相同的插槽。這叫做碰撞。插入將會更慢,因爲在碰撞後容器將不得不檢查已經在該插槽中的物體是否與新的物體相匹配(equals)。另外,檢索速度會比較慢,因爲它必須依次檢查它們,直到找到正確的(equals againg)。最後,可能會有很多未使用的內存被浪費在不被使用的插槽中。

實質上,通過不實現明智的散列碼,您將轉換列表中的散列容器(以及低效的散列容器)。

0

如果我們評論hashCode()它返回3,這也是正確的。

這是不正確的!只有2個不同的對象:「a」和「b」。平等的方法說什麼是平等的,什麼不是。預期的大小是2.但是,因爲equals-hashcode合同被破壞,返回的大小爲3.