クラスのequals()メソッドでは、プライベートインスタンスHashMap変数を使用して、同等性を比較しています。ただし、HashMap変数を比較すると、2つの異なるオブジェクトが依然として等しいことを示しています。さらなる調査により、リンクに到達しました: ここにリンク 。ただし、HashMap1.equals(HashMap2)が機能しない理由は、「カスタマイズされたコードを記述しない限り、Javaの配列が同等かどうかをテストできないため」というだけです。
私はこの理由を理解していませんでした。誰でも私に手の込んだ理由を教えてもらえますか?
Java配列型のequals
メソッドは==
と同等です。なぜなら、Java配列の「クラス」はObject.equals
をオーバーライドしないからです。
配列を「値で」比較する場合は、適切なJava.util.Arrays.equals(...)
メソッドを使用するか、自分で実装する必要があります。
HashMap
が配列をキーまたは値として使用する場合、配列のequals
メソッドを呼び出して、2つのマップ間でキーや値が同じかどうかをテストします。これにより、HashMap.equals
の動作がおかしくなります(あなたの観点から)。それはリンクされた記事が言っていることです。ただし、配列セマンティックonlyは、配列をキーまたは値クラスとして使用する場合、HashMap
の等価性に影響します。そうしない場合、HashMap::equals
は期待どおりに動作するはずです。
Map
クラスの同等性に関するjavadocは少し複雑ですが、基本的には2つのエントリセットを取得し、サイズを比較してからs1.containsAll(s2)
を実行することになります。もちろん、これは高価ですが、shouldMap
インターフェイスを正しく実装するすべてのMap
クラスで機能します。
配列をマップのキーとして使用することは、いくつかの理由で悪い考えであることに注意してください。
equals
およびhashCode
のセマンティクスは、ほとんどのシナリオでHashMap
に対して間違っています。ほとんどのユースケースでは、オブジェクトIDではなく値でキーを比較するマップが必要です。equals
/hashcode
問題の回避策があると仮定した場合、still配列キーを変更してマップの不変式を破ることができます。記事は正しいです。キーオブジェクトと値オブジェクトが同じメソッドを使用して比較できる限り、equals()メソッドを使用してハッシュマップを安全に比較できます。この記事では、マップ値は配列であり、期待どおりにequals()を実装していません。代わりにArrayListを使用すると、問題は解決します。
ネイティブJava配列には.equals()関数がありません。したがって、ハッシュマップの値(またはキーと思われるキー)が配列の場合、HashMap.equals()は失敗します。 Object.equals()にフォールバックし、2つのオブジェクトが実際に同じオブジェクトであるかどうかを確認するだけです。
_// something like this
class Object {
public boolean equals( Object o) {
return this == o;
}
}
_
コンテナには、同じ参照であるかどうかを単にチェックするのではなく、コンテナの連続する要素でequals()を呼び出す独自の.equals()があるため、array []ではなくContainerでバリアントを使用することで問題を回避できます。 。 Collection.equals実装のコードは次のようになります。
_public boolean equals(Object o) {
// sets never equal lists and visa versa
if (o instanceof MyCollectionSubclass) {
Iterator myIterator = iterator();
Iterator theirIterator = ((Collection)o).iterator();
while (myIterator.hasNext() && theirIterator.hasNext()) {
Object myObj = myIterator.next();
Object theirObj = theirIterator.next();
if (!myObj.equals(theirObj)) {
return false;
}
}
// at least one will be false or we wouldn't have left the above while loop
return myIterator.hasNext() == theirIterator.hasNext();
}
// not our class
return false;
}
_
これにより、equals()
を呼び出したときにコレクションのコンテンツが何をするかに応じて、真の値の比較が生成される場合があります。
Javaの配列は、カスタマイズされたコードを記述せずに同等性をテストできません
これはJava配列がObject.equals()
をオーバーライドしないことを示す複雑な方法です。したがって、equals()
(これはequals
すべてのコレクションクラスのメソッドが実行します)、「値の等価性」ではなく「インスタンスの等価性」を取得します。
これは、オーバーライドされているかどうかに応じて、equals
が機能するさまざまな方法の特別なケースです。