AbstractMap的哈希码覆盖是有问题的

时间:2012-06-17 13:33:45

标签: java map hashcode

在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。如果您正在编写自己的哈希码,您可能想知道这一点。

我可以想到至少有一个有用的哈希码定义可能与此相反,而且它似乎对hashmap中的数据量很敏感。具体来说,映射中的数据越多,entrySet越大,哈希码的运行总量就越大。

这看起来似乎是一种无证的副作用,也只是一个普通的坏主意。目的似乎是利用加法的交换定律(a + b == b + a)来生成具有相同条目的映射所需的相等,但是哇,这是一个糟糕的实现。

这要求任何人重写哈希码 - 任何不仅仅想要对象 - 实例品牌平等(==即大多数人)的人,要知道他们不能或不可能知道的事情。第一个是他们的哈希码(谁想到这个?)的累积总和,另一个是将要输入到地图中的最大项目数以及它如何影响累积总和。

这只是被涂鸦了。有人有任何见解吗?如果重要的话,hashcode()是从Object类派生的。

1 个答案:

答案 0 :(得分:4)

int将会wrap around / overflow所以上面的 Integer.MAX_VALUE会抛出异常或导致问题。

这里的主要概念是hashCode应该为被认为相同的对象(在程序的特定运行中)产生相同的(整数)值。此代码符合该要求。

请注意,哈希码冲突可能会偶尔发生,在覆盖equals时,您始终需要提供有意义的hashcode覆盖。