32

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

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

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

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

}

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

}

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

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

4

5 に答える 5

85

equals()inの独自の実装を提供する必要がありますMyClass

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

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

于 2013-04-17T20:00:23.067 に答える
7

と をオーバーライドする必要がequalsありhashCodeます。
equalsは、必要なプロパティに従ってオブジェクトが等しいかどうかを比較します。これは、オブジェクトが およびでhashCode正しく使用されるために必須です。CollectionsMaps

于 2013-04-17T20:00:31.363 に答える
6

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

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

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

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

于 2013-04-17T20:01:49.340 に答える
5

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

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

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

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

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

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

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

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

equals() と hashCode() を簡単に実装できるようにする apache commons の 2 つのクラスを見てください。

于 2013-04-17T19:59:37.077 に答える
2

1) == この場合、参照の等価性を評価します
2) 等価性についてはよくわかりませんが、単純に比較メソッドをオーバーライドして MyClass 内に植えてみませんか?

于 2013-04-17T20:00:37.753 に答える