2011-03-31 4 views
6

が含まれている私のコードです:その仕様にmentionnedとしてHashSetのは、ここでの方法、奇妙な行動

public class testGui { 



    public static void main(String[] arg){ 
     class TESTS{ 
      String t; 

      public TESTS(String t){ 
       this.t = t; 
      } 

      @Override 
      public boolean equals(Object x){ 
       System.out.println("My method is called..."); 
       if(x instanceof TESTS){ 
        TESTS zzz = (TESTS) x; 
        return zzz.t.compareTo(t)==0; 
       } 
       else return false; 
      } 
     } 
     HashSet<TESTS> allItems = new HashSet<TESTS>(); 
     allItems.add(new TESTS("a")); 
     allItems.add(new TESTS("a")); 
     System.out.println(allItems.contains(new TESTS("a"))); 
    } 

} 

HashSetのメソッドが含まれている理由は、私は得ることはありませんが、私のequalsメソッドを呼び出していません。

より正式にこれは は、いかなる要素eが含まれていない設定した場合、このセットには、O、指定 要素を追加し、その (O == NULL E == NULL:o.equals(e)参照)

私のコードはfalseを返すので、私のequalsメソッドには入っていません。

お返事ありがとうございます!

答えて

13

equalsを上書きする場合は、hashCodeも上書きする必要があります。そうでなければ、等しいオブジェクトは異なるハッシュコードを持ち、等しくないとみなされます。

のみを無効にしないことを強くお勧めします。hashCode。しかし、不等なオブジェクトは同じハッシュコードを持つ可能性があるため、これは必須ではありません。

+2

これらは等しくないとはみなされません。 HashSetはequalsメソッドを呼び出すことさえしません。なぜなら、同じバケットにつながるhashCodeのためだけであるからです。また、hashCodeだけをオーバーライドすることは意味がありません。なぜならHashSetは常に同じhashCodesを持つオブジェクトに対してequalsを呼び出すからです。 –

+0

@JB、はい、異なるバケットにつながるということは、それらが「不等」(異なるオブジェクトとみなされる)とみなされることを意味します。私はその用語を使用するときに 'equals'メソッドを参照しているわけではありません。私はまた、 'hashCode'だけをオーバーライドすることは非論理的であることに同意します。それが私がそれに対して強く勧めている理由です。しかし、それは契約を破ることはありません。 –

+1

Javaのマニュアルでhashcodeが最初に呼び出されたと書かれていれば、うれしいでしょう。私はちょうどこの問題でJava 5で燃えてしまった。 – Aaron

3

equalsと一致するように、hashCodeも実装する必要があります。 HashSetは、hashCodeメソッドを使用してアイテムを入れるバケットを決定し、2アイテムのハッシュコードが同じ場合にのみequalsを呼び出します。

効果的なJavaの第2版項9にこのルール(と、それを壊すの結果を)説明します。あなたはequalsをオーバーライドする場合は、必ずhashCodeをオーバーライドします。

+0

多くの人に感謝、それは本当に役立った、私はあなたが答えた前に答えを見つけた(質問をキャンセルする方法を知らなかった)が、あなたが書いたものは、それは私の問題を解決した;)。 – Abbadon

7

HashSetは、各オブジェクトのHashCodeに依存します。 equalsメソッドが呼び出される前に、hashCodeメソッドが呼び出されます。ハッシュコードが等しい場合、ハッシュセットはequalsメソッドを評価する価値があるとみなします。

はhashCodeメソッドを実装するようであればa.equals(B)== trueの場合は、その後、a.hashCode()== b.hashCode()

、それはあなたが期待するよう作業を開始する必要があります。

0

ほとんどのコメントは...単にhashcodeメソッドをオーバーライドしています(下記のサンプルを参照)。

@Override 
     public int hashCode() { 
      return t.hashCode()*31; 
     } 
+0

31を乗算すると何が得られますか? –

+0

このスレッドは役立ちますhttp://stackoverflow.com/questions/299304/why-does-javas-hashcode-in-string-use-31-as-a-multiplier – Prasanna