1. ホーム
  2. java

[解決済み] JavaでequalsとhashCodeをオーバーライドする際に考慮すべき事項は?

2022-03-16 09:50:32

質問

オーバーライドする際の問題点・落とし穴は? equalshashCode ?

解決方法は?

理論(言語弁護士と数学に興味のある人向け)。

equals() ( ジャバドック ) は、同値関係を定義しなければなりません (それは必ず 反射的 , シンメトリック および 推移的 ). さらに、以下の条件を満たす必要があります。 一貫性 (オブジェクトが変更されなければ、同じ値を返し続けなければならない)。さらに o.equals(null) は常にfalseを返さなければならない。

hashCode() ( ジャバドック ) も必要です。 一貫性 (の観点からオブジェクトが変更されない場合)。 equals() の場合、同じ値を返し続けなければならない)。

リレーション の2つのメソッドの間にある。

いつ a.equals(b) であれば a.hashCode() と同じでなければなりません。 b.hashCode() .

実際に使ってみると

片方をオーバーライドしたら、もう片方もオーバーライドしてください。

を計算するために使用するフィールドのセットと同じものを使用します。 equals() を計算するために hashCode() .

優れたヘルパークラスを使用する EqualsBuilder HashCodeBuilder から アパッチコモンズラング ライブラリを使用します。一例です。

public class Person {
    private String name;
    private int age;
    // ...

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
            // if deriving: appendSuper(super.hashCode()).
            append(name).
            append(age).
            toHashCode();
    }

    @Override
    public boolean equals(Object obj) {
       if (!(obj instanceof Person))
            return false;
        if (obj == this)
            return true;

        Person rhs = (Person) obj;
        return new EqualsBuilder().
            // if deriving: appendSuper(super.equals(obj)).
            append(name, rhs.name).
            append(age, rhs.age).
            isEquals();
    }
}

また、覚えておいてください。

ハッシュベースの コレクション または 地図 というように ハッシュセット , LinkedHashSet , ハッシュマップ , ハッシュテーブル または ウィークハッシュマップ コレクションに入れたキーオブジェクトのhashCode()が、そのオブジェクトがコレクションにある間は決して変化しないことを確認します。これを確実にする方法は、キーをイミュータブルにすることです。 これには他の利点もあります。 .