2012-06-20 10 views
22
class temp { 
int id; 

public int getId() { 
    return id; 
} 

temp(int id) { 
    this.id = id; 
} 

public void setId(int id) { 
    this.id = id; 
} 

@Override 
public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (getClass() != obj.getClass()) 
     return false; 
    temp other = (temp) obj; 
    if (id != other.id) 
     return false; 
    return true; 
} 
} 

public class testClass { 

    public static void main(String[] args) { 
     temp t1 = new temp(1); 
     temp t2 = new temp(1); 
     System.out.println(t1.equals(t2)); 
     Set<temp> tempList = new HashSet<temp>(2); 
     tempList.add(t1); 
     tempList.add(t2); 
     System.out.println(tempList); 
} 

プログラムは、両方の要素をセットに追加します。最初に私はショックを受けました。なぜなら、設定するメソッドを追加するときに、equalsメソッドが呼び出されるからです。hashCode()がオーバーライドされていない場合、HashSetは重複項目の挿入を許可します

しかし、私はhashCodeメソッドオーバーライド:

@Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + id; 
     return result; 
    } 

をし、それは追加しませんでした。 JavadocのSetとadd()メソッドは、Setに追加中にequals()だけをチェックするので、これは驚くべきことです。

そして、これは追加のJavadoc(IS):

/** 
    * Adds the specified element to this set if it is not already present. 
    * More formally, adds the specified element <tt>e</tt> to this set if 
    * this set contains no element <tt>e2</tt> such that 
    * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>. 
    * If this set already contains the element, the call leaves the set 
    * unchanged and returns <tt>false</tt>. 
    * 
    * @param e element to be added to this set 
    * @return <tt>true</tt> if this set did not already contain the specified 
    * element 
    */ 
    public boolean add(E e) { 
     return map.put(e, PRESENT)==null; 
    } 

そしてIはHashSetのは、ハッシュマップとして実装され、マップに、オブジェクトのハッシュコードをキーとして使用されていることに気づきました。したがって、hashCodeをオーバーライドしないと、異なるキーを使用してそれらを処理しています。

これはadd()メソッドのマニュアルか、HashSetのドキュメントにあるべきではありませんか?

+2

hashCode()関数が存在する全理由は、ハッシュベースのコレクションのためです。コレクションは、定義していない場合にどのようなハッシュ関数を使用するかを「知る」べきですか? –

+0

私は、クラスtempのequals()メソッドがこの場合(sysoutを試してみた)決して呼び出されないので、JVMの契約を満たすためにhashCode()を実装していなければ、JVMはデフォルトのequals仕様。面白い !!!!!!! –

+2

'hashCode()'が同じ場合にのみ、 'equals'を呼び出します。それをオーバーライドすると、デフォルトの等号が呼び出されません。 –

答えて

20

これは文書化されています。 2つのオブジェクトが等しい(オブジェクト)によると等しいある場合、二つの物体のそれぞれにhashCodeメソッドを呼び出し が を生成しなければならない、方法

:それはhashCode()に言うjava.lang.Objectのマニュアルを参照してください同じ整数が返されます。このメソッドがオーバーライドされたときに一般的な を維持するように、hashCodeメソッド をオーバーライドすることが必要であること

注:また、以下をObject.equals(Object)方法のマニュアルに見出される

等しいオブジェクトは が等しいハッシュコードを持たなければならないというhashCodeメソッドの契約。言い換えれば

、あなたのクラスにinstanceA.equals(instanceB) == trueinstanceA.hashCode() != istanceB.hashCode()あなたはObjectクラスの契約に違反する事実にある場合。

+1

私は常にequals()とhashCode()の両方をオーバーライドする必要がありますが、予測できない結果が生じることはありませんでした。また、Setおよびadd()メソッドのドキュメントでは、equalsメソッドをオーバーライドする必要があると明示されているので、hashCode()については言及していません。契約はそれをすべてexlpains。 –

+0

@DhwaneetBhatt私は助けになることができてうれしいです。実際にオブジェクトをJavaのセットに格納するときは、両方のメソッドを実装することが重要です。私はそれが明らかであるか、または即座にそうする必要がないときに見過ごされるべきであると言っているわけではない。しかし、適切な(契約ごとの)実装は、夢見ることは非常に自明ではありません。 – Kallja

+0

答えをありがとう! –

14

だけequals()ドキュメントでも見てみましょう:

述べhashCodeメソッドの汎用規約を維持するように、このメソッドをオーバーライドするたびにhashCodeメソッドをオーバーライドすることが一般的に必要であることに注意してください等しいオブジェクトは等しいハッシュコードを持つ必要があります。

実際、equals()hashCode()は強く結びついています。これらの一貫性の問題を避けるために、どちらか一方と協力して作業するときは、両方とも常に考慮する必要があります。

+0

私はちょうど今日、難しい方法を学んだ:) –

+0

質問のジャックなぜ等しい();メソッドにはObject型のパラメータがありますか?依然として鋳造していても、ダイレクト・テンポラリ・クラス・タイプのパラメータはなぜですか – UnKnown

8

equals()をオーバーライドする場合、は、もhashCode()をオーバーライドする必要があります。

Objectのドキュメントに列挙されているequals()およびhashCode()の動作にはいくつかの制限があります。具体的には、等号()メソッドは、次の特性を示さなければならない:

  • 対称性:2つの参照、AとB、a.equalsについて(b)の場合にのみb.equals(A)
  • 再帰性すべてのnull以外の参照の場合、a.equals(a)
  • 可搬性:a.equals(b)およびb.equals(c)の場合、a.equals(c)
  • hashCode()との一貫性:等しい2つのオブジェクトは同じhashCode()値を持つ必要があります

this詳細については。

+0

ありがとうございました –

+1

Mathematicsにはどこからでもあらゆるものが影響を受けています) –

1
彼ら(のjavadoc人は)彼らは( HashSetadd()方法のドキュメントを)言うときことを事前に想定している場合があります

hashCode()は、それらの両方のために、本質的に同じです。

+1

Setを使う人は、Object.equals(Object)などの関連するメソッドに精通している必要があるため、推定は有効です。それぞれのメソッドのドキュメントによれば、Object.hashCode()メソッドに強くリンクされています。 – Kallja

+0

@ヤルコ:更新されたアンサーをご覧ください –

関連する問題