web-dev-qa-db-ja.com

2つのJavaオブジェクトを比較する方法

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

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

両方のプロパティをまったく同じ値に設定し、それらが同じであることを確認した場合

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

}

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

}

ただし、これらのアプローチはどちらも真の値を返しません。それぞれのプロパティをチェックしましたが、それらは一致しています。

これら2つのオブジェクトを比較して、それらが同一であることを確認するにはどうすればよいですか?

29
Roy Hinkley

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;
}

ハッシュ関数の実装の詳細については、 この質問 を参照してください。

79
John Kugelman

equalsおよびhashCodeをオーバーライドする必要があります。
equalsは、必要なプロパティに従ってオブジェクトを比較します。オブジェクトをhashCodeおよびCollectionsで正しく使用するには、Mapsが必須です。

7
Cratylus

クラスObjectのメソッドequals()を正しくオーバーライドする必要があります

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

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

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

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

もう1つポイントがあります。一部のコレクションでは、パフォーマンス上の理由だけでなく、キーとして使用されるクラスでhashCode()メソッドを適切に実装する必要があります。例は次のとおりです。HashSetおよびLinkedHashSet。 hashCode()をオーバーライドしない場合、デフォルトのObject hashCode()メソッドにより、「意味的に等しい」と考えられる複数のオブジェクトを「重複禁止」セットに追加できます。

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

  • ハッシュセット
  • LinkedHashSet
  • ハッシュマップ

Equals()とhashCode()を簡単に実装できるApache commonsの2つのクラスをご覧ください

5
rarry

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

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

equals()が機能しなかった理由は、まだ自分で実装していないためです。デフォルトの動作は==と同じものだと思います。

多くのJava.utilコレクションがそれを期待しているため、hashcode()を実装する場合は、equals()も実装する必要があることに注意してください。

5
Daniel Kaplan

1)==この場合、参照の等価性を評価します
2)イコールについてはあまりよくわかりませんが、単に比較メソッドをオーバーライドしてMyClass内に配置しないのはなぜですか?

2
Infested