2011-05-14 108 views
6

我遇到了一個有趣的問題,我敢肯定是HashMap的錯。請看下面的調試代碼(AMAP是一個HashMap,關鍵是傳遞給此方法的值)HashMap說鑰匙不存在,即使它

System.out.println("getBValues - Given: " + key); 
System.out.println("getBValues - Contains Key: " + AMap.containsKey(key)); 
System.out.println("getBValues - Value: " + AMap.get(key)); 
for(Map.Entry<A,HashSet<B>> entry : AMap.entrySet()) { 
    System.out.println("getBValues(key) - Equal: " + (key.equals(entry.getKey()))); 
    System.out.println("getBValues(key) - HashCode Equal: "+(key.hashCode() == entry.getKey().hashCode())); 
    System.out.println("getBValues(key) - Key: " + entry.getKey()); 
    System.out.println("getBValues(key) - Value: " + entry.getValue()); 
} 

現在,在這個地圖我插入一個鍵(頻道)和值。後來我試着和get()獲得價值背部和運行這個調試代碼,在我的情況下,給出了這樣的輸出:

getBValues - Given: Channel(...) 
getBValues - Contains Key: false <--- Doesnt contain key?! 
getBValues - Value: null <--- Null (bad) 
getBValues(key) - Equal: true <--- Given key and AMap key is equal 
getBValues(key) - HashCode Equal: true 
getBValues(key) - Key: Channel(Same...) 
getBValues(key) - Value: [] <--- Not null (This is the expected result) 

正如你所看到的,取出由HashMap中的鍵直接不工作,但我通過循環得到完全一樣的密鑰,這意味着它只能在get()找不到。我的問題是什麼會造成這種情況? get()如何找不到存在的密鑰?

我會提供一些這樣的代碼示例,但我似乎無法獨立重現此。

有什麼建議可能會導致這種情況?

+3

*「......我很確定是HashMap的錯誤」*。跟着我重複一遍。 「錯誤在**我的**代碼中。」 - http://storm.stackexchange.com/questions/1785/what-should-every-programmer-know-about-programming/1842#1842 – 2011-05-14 04:54:09

+0

@Stephen我的意思是更多的「在HashMap中的某些'功能'造成這個「 – TheLQ 2011-05-14 04:59:01

回答

4

從我所看到的,我們仍然沒有排除,如果有做不變性。 如果你這樣做:

aMap.put(key, value); 
key.setFieldIncludedInHashCodeAndEquals(25); 

那麼你會得到上面的結果。

要在你的榜樣排除這個可能性,無論是向我們展示更多的代碼,或在for循環以上,加

System.out.println(aMap.get(entry.getKey())); 

此外,使用調試器。這樣,你可以看到你的物體是否在正確的桶中。

+0

嗯......給了我一個空值。我猜hashCode在添加後會改變。我會看看我是否可以將我的代碼更新爲可行。 – TheLQ 2011-05-14 05:11:13

+0

因此,在將對象添加到地圖後,是否有任何字段作爲hashCode的一部分或等於您在地圖中存儲爲鍵的對象時發生了變化? – Buhb 2011-05-14 05:14:02

+0

這就是爲什麼地圖中的鍵必須是不可變的。 – duffymo 2011-05-14 13:55:05

8

我敢打賭,你沒有在你的關鍵Channel類中正確地覆蓋equals和hashCode。這將解釋它。

約書亞·布洛克告訴你如何正確地做到這一點在他的「有效的Java」第3章

http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf

+0

我做過龍目島項目,甚至在課堂上專門排除了2個影響平等的HashSet。 – TheLQ 2011-05-14 04:05:47

+0

我不知道龍目島是什麼,我無法分辨這是否意味着「是的,我有一個合適的equals和hashCode實現。」如果密鑰是不可變的,那麼最好。您的頻道是否屬實? – duffymo 2011-05-14 04:11:43

+1

在他特定的測試中,hashCode爲密鑰和存儲密鑰提供相同的值。它可能被錯誤地或正確地執行,但這個例子是正確的。 key.equals(entry.key)也是正確的。唯一剩下的原因是我可以看到entry.key.equals(key)是否爲false。 – 2011-05-14 04:25:02