2013-04-17 23 views
25

同じクラスからインスタンス化された2つのJavaオブジェクトがあります。2つのJavaオブジェクトを比較する方法

MyClass myClass1 = new MyClass(); 
MyClass myClass2 = new MyClass(); 

私は正確に同じ値にそのプロパティの両方を設定し、それらが同じ

if(myClass1 == myClass2){ 
    // objects match 
    ... 

} 

if(myClass1.equals(myClass2)){ 
    // objects match 
    ... 

} 

であることを確認した場合しかし、これらのアプローチのどちらが真の値を返します。私はそれぞれのプロパティをチェックして一致します。

これらの2つのオブジェクトを比較して、それらが同一であることを確認するにはどうすればよいですか?あなたは正しくメソッドをオーバーライドする必要が

+0

私はGoogleでそれを行いましたが、あなたがequalsメソッドをオーバーライドしなければならないと説明した例はありませんでした。 –

+0

@AndroidAddict:なぜあなたはその質問をしませんでしたか? –

答えて

71

あなたはMyClassequals()の独自の実装を提供する必要があります。

@Override 
public boolean equals(Object other) { 
    if (!(other instanceof MyClass)) { 
     return false; 
    } 

    MyClass that = (MyClass) other; 

    // Custom equality check here. 
    return this.field1.equals(that.field1) 
     && this.field2.equals(that.field2); 
} 

ハッシュテーブルで使用されている、あなたのオブジェクトのいずれかのチャンスがあります場合にも、hashCode()をオーバーライドする必要があります。ハッシュ関数の実装の詳細については

@Override 
public int hashCode() { 
    int hashCode = 1; 

    hashCode = hashCode * 37 + this.field1.hashCode(); 
    hashCode = hashCode * 37 + this.field2.hashCode(); 

    return hashCode; 
} 

参照this questionreasonable implementationのようなもので、オブジェクトのフィールドのハッシュコードを組み合わせることであろう。

+1

なぜ37ですか?プライム? – Aubin

+1

@Aubin通常、ハッシュコードの生成には素数が使用されます。私が間違っていないと、生成されたハッシュに衝突が発生する可能性が減ります。なぜ37を使うのかについては、普段の選択だと思いますが、私は13の代わりに37を使う特別な理由はわかりません。 – afsantos

+0

本当にありがとうございます。誰もが私を正しい道につけましたが、私はただ正しいものとして受け入れることができます。 –

5

は等しい()クラスObjectから

編集:私はあまりにも正確ではなかったので、私の最初の反応は、おそらく誤解されたと思います。だから私はもっと説明を加えることにしました。

なぜequals()をオーバーライドする必要がありますか?これは、開発者が2つのオブジェクトが同等であることが何を意味するのかを決定する領域にあるためです。ほとんどの場合、参照平等では不十分です。

たとえば、キーがタイプPersonのHashMapがあるとします。それぞれの人は名前と住所を持っています。ここで、キーを使って詳細なBeanを探したいとします。問題は、通常、マップ内の参照と同じ参照を持つインスタンスを作成できないことです。あなたがするのは、クラスPersonの別のインスタンスを作成することです。明らかに、演算子==はここでは動作せず、equals()を使用する必要があります。

しかし今、別の問題が発生しています。あなたのコレクションが非常に大きく、検索を実行したいと考えてみましょう。純粋な実装では、キーオブジェクトをequals()を使用してマップ内のすべてのインスタンスと比較します。しかし、それは非常に広大であろう。そしてここにhashCode()が来る。他の人が指摘しているように、ハッシュコードは一意の番号ではありません。重要な要件は、equals()が2つのオブジェクトに対してtrueを返す場合、hashCode()は両方のオブジェクトに対して同じ値を返さなければならないということです。逆の意味は成立しません。これは良いことです。なぜなら、ハッシュコードは私たちの鍵を種類のバケットに分けるからです。単一のバケットにクラスPersonのインスタンスが少数しかありません。検索を実行すると、アルゴリズムはすぐに正しいバケットにジャンプし、各インスタンスに対してequalsを実行するだけです。したがって、hashCode()の実装は、オブジェクトを可能な限り均等にバケットに分散する必要があります。

もう1つポイントがあります。コレクションによっては、パフォーマンス上の理由だけでなく、キーとして使用されるクラスでhashCode()メソッドを適切に実装する必要があるコレクションもあります。例は、HashSetとLinkedHashSetです。それらがhashCode()をオーバーライドしない場合、デフォルトのオブジェクト hashCode()メソッドは、 "重複が許可されていません"セットに "重要な意味で と等しい"とみなされる複数のオブジェクトを追加します。

のhashCodeを使用するコレクションの一部()

  • HashSetの
  • LinkedHashSetの
  • HashMapの

あなたが実装できるようになりますApacheのコモンズからこれら二つのクラスを見てください()とhashCode()は簡単に

7

equalshashCodeを上書きする必要があります。
equals)あなたが必要な特性に応じて平等のためのオブジェクトを比較し、hashCodeあなたのオブジェクトがCollectionsMaps

2

1で正しく使用するために必須であるだろう==この場合
2の参照平等を評価)私はequalsについてはあまり確かではありませんが、単にcompareメソッドをオーバーライドしてMyClassの中に植え付けてみませんか?

5

MyClassにequals()メソッドを実装する必要があります。

==が機能しなかったのは、同じインスタンスを参照していることを確認しているためです。それぞれについてnewを行ったので、それぞれ異なるインスタンスです。

equals()がうまくいかなかったのは、まだ自分で実装していないからです。私はそれがデフォルトの動作は==と同じことだと思う。

equals()を実装する場合は、多くのjava.utilコレクションで期待されているため、hashcode()も実装する必要があります。

+0

にあります。短いとポイントに。 – tommyO

関連する問題