2012-06-17 22 views
2

雖然細讀源AbstractMap在Java中我碰到這個跑:AbstractMap的壓倒一切的是有問題的

440  /** 
441  * Returns the hash code value for this map. The hash code of a map is 
442  * defined to be the sum of the hash codes of each entry in the map's 
443  * <tt>entrySet()</tt> view. This ensures that <tt>m1.equals(m2)</tt> 
444  * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps 
445  * <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of 
446  * {@link Object#hashCode}. 
447  * 
448  * <p>This implementation iterates over <tt>entrySet()</tt>, calling 
449  * {@link Map.Entry#hashCode hashCode()} on each element (entry) in the 
450  * set, and adding up the results. 
451  * 
452  * @return the hash code value for this map 
.... 
456  */ 
457  public int hashCode() { 
458  int h = 0; 
459  Iterator<Entry<K,V>> i = entrySet().iterator(); 
460  while (i.hasNext()) 
461   h += i.next().hashCode(); 
462  return h; 
463  } 

這是因爲它的有趣 - 看似偶然 - 在散列碼的方式排除了。

如果此方法按照書面方式工作,則它將排除使用總計在一起時超過Integer.MAXINT的哈希碼。如果你正在編寫自己的哈希碼,你可能想知道這一點。

我可以想到至少有一個有用的散列碼定義可能與此相沖突,而且它似乎對散列表中的數據量非常敏感。具體來說,map中的數據越多,entrySet越大,哈希碼的運行總數就越大。

這看起來像一個無證的副作用,也只是一個普通的舊壞主意。目的似乎是利用交換法的加法(a + b == b + a)來產生具有相同條目的地圖所需的相等性,但哇,這是多麼糟糕的實現。

這需要任何人重寫散列碼 - 這是任何人不想僅僅是對象實例品牌平等(即大多數人),知道他們不能或不可能知道的事情。第一個是它們的哈希碼的累積和(誰曾想過這個??),另一個是將要輸入到地圖中的項目的最大數量以及這可能如何影響累積和。

這只是亂塗亂畫。任何人有任何見解? hashcode()是從類Object派生的,如果它很重要的話。

回答

4

intwrap around/overflow所以上述 Integer.MAX_VALUE的打算拋出一個異常,這裏會出現問題。

這裏的主要概念是,hashCode應該爲被認爲是相同的對象(在程序的特定運行中)產生相同的(整數)值。此代碼符合該要求。

請注意,散列碼碰撞可能並將偶爾發生,這就是您在覆蓋hashcode時總是需要提供有意義的equals覆蓋。

+0

謝謝!我完全忘記了整數環繞。 –

+0

的確,幾乎_all_(正確實現!)'hashCode'函數可能會導致整數溢出,但這是_okay._ –