web-dev-qa-db-ja.com

Javaコレクションの設定-equalsメソッドのオーバーライド

equalsデータ型で使用されるSetメソッドをオーバーライドする方法はありますか? equalsというクラスのカスタムFeeメソッドを作成しました。現在、LnkedListFeeがあり、重複したエントリがないことを確認したいと思います。したがって、Setの代わりにLinkedListを使用することを検討していますが、2つの料金が等しいかどうかを判断する基準は、equalsクラスのオーバーライドされたFeeメソッドにあります。

LinkedListを使用する場合、すべてのリスト項目を反復処理し、パラメーターとして残りのエントリを使用して、equalsクラスのオーバーライドされたFeeメソッドを呼び出す必要があります。これだけを読むと、処理が多すぎるように聞こえ、計算が複雑になります。

Setをオーバーライドされたequalsメソッドで使用できますか?したほうがいい?

20
Faiyet

ジェフ・フォスターが言ったように:

Set.equals()メソッドは、2つのセットが等しいかどうかを比較するためにのみ使用されます。

Setを使用して重複エントリを取り除くことができますが、注意してください:HashSetは、含まれているオブジェクトのequals()メソッドを使用して同等性を判断しないでください。

HashSetは、<Integer(HashCode), Object>エントリを持つ内部HashMapを持ち、equals()とHashCodeのequalsメソッドを使用して、等しいかどうかを判断します。

この問題を解決する1つの方法は、セットに入れたクラスのhashCode()をオーバーライドして、equals()基準を表すようにすることです。

例えば:

class Fee {
      String name;

  public boolean equals(Object o) {
      return (o instanceof Fee) && ((Fee)o.getName()).equals(this.getName());
  }

  public int hashCode() {
      return name.hashCode();
  }

}
35
Jonas Eicher

Setを使用して、オーバーライドされたequalsメソッドでオブジェクトタイプを保持できますが、hashCode()もオーバーライドする必要がある場合があります。等しいオブジェクトはハッシュコードが等しい。

例えば:

public Fee{

    public String fi;

    public String fo;

    public int hashCode(){

        return fi.hashCode() ^ fo.hashCode();
    }

    public boolean equals(Object obj){

        return fi.equals(obj.fi) && fo.equals(obj.fo);
    }
}

(もちろん、必要に応じてnullチェックを使用します。)

多くの場合、セットはhashCode()を使用してパフォーマンスを最適化し、hashCodeメソッドが破損していると誤動作します。たとえば、 HashSetは内部HashMapを使用します。

HashMapのソースコードを確認する場合 、要素のhashCode()メソッドとequals()メソッドの両方に依存していることがわかります。

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

ハッシュが正しく生成されない場合、equalsメソッドが呼び出されることはありません。

セットを高速化するには、可能な限り、等しくないオブジェクトに対して個別のハッシュコードを生成する必要があります。

8
SharkAlley

Setは、セットに追加されたオブジェクトのequalsメソッドを使用します。 JavaDoc 状態

重複する要素を含まないコレクション。より正式には、セットにはe1.equals(e2)などの要素e1とe2のペアは含まれず、最大1つのnull要素が含まれます。

Set.equals()メソッドは、2つのセットが等しいかどうかを比較するためにのみ使用されます。セットへのアイテムの追加/削除の一部として使用されることはありません。

5
Jeff Foster

解決策の1つは、コンパレータで TreeSet を使用することです。

ドキュメントから:

TreeSetインスタンスは、compareTo(またはcompare)メソッドを使用してすべての要素比較を実行するため、このメソッドで等しいと見なされる2つの要素は、セットの観点からは等しいです。

このアプローチは、LinkedListを使用するよりもはるかに高速ですが、HashSetよりも少し遅くなります(ln(n)vs n)。

TreeSetを使用する1つの副作用として、セットがソートされることに注意してください。

1
PaulrBear