2

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を超えるハッシュコードを使用できなくなります。独自のハッシュコードを作成している場合は、これについて知りたいと思うかもしれません。

私はこれに反する可能性のあるハッシュコードの少なくとも1つの有用な定義を考えることができ、さらにそれはハッシュマップ内のデータの量に敏感であるように思われます。具体的には、マップ内のデータが多いほど、entrySetが大きくなり、ハッシュコードの現在の合計が大きくなります。

これは実際には文書化されていない副作用のようであり、単なる古い悪い考えでもあります。目的は、可換加算の法則(a + b == b + a)を利用して、同じエントリを持つマップの必要な等式を生成することであるように見えますが、すごい、なんて悪い実装でしょう。

これには、ハッシュコードをオーバーライドする人(つまり、オブジェクトインスタンスのブランドの平等(==つまりほとんどの人)だけを望まない人)が、知らない、または知る可能性が低いことを知る必要があります。1つはハッシュコードの累積合計(誰がこれを考えたことがありますか??)であり、もう1つはマップに入力されるアイテムの最大数であり、それが累積合計にどのように影響するかを示します。

これはいたずら書きです。誰か洞察がありますか?hashcode()は、重要な場合はクラスObjectから派生します。

4

1 に答える 1

4

intラップアラウンド/オーバーフローするため、Integer.MAX_VALUEを超えると、ここで例外がスローされたり、問題が発生したりすることはありません。

ここでの主な概念は、hashCode(プログラムの特定の実行において)同一であると見なされるオブジェクトに対して同一の(整数の)値を生成する必要があるということです。このコードはその要件を満たしています。

ハッシュコードの衝突は時折発生する可能性があり、発生する可能性があることに注意してください。equalsオーバーライドするときは、常に意味のあるオーバーライドを提供する必要がありますhashcode

于 2012-06-17T13:47:35.813 に答える