hashcodeとequalsはなぜ同時に書き直すのか


hashcode()とequals()を書き換える理由について簡単に説明します.
まず、この2つの方法はいずれもObjectオブジェクトから来ており、APIドキュメントに基づいて元の意味を確認します.(1)public boolean equals(Objectobj)は、任意の非空参照値xおよびyについて、xおよびyが同じオブジェクトを参照している場合にのみtrueを返す.注意:このメソッドが書き換えられる場合、hashCodeメソッドは、通常、hashCodeメソッドの通常の協定を維持するために書き換える必要があり、この協定は、等しいオブジェクトが等しいハッシュコードを有しなければならないことを宣言する.(2)public int hashCode()は、そのオブジェクトのハッシュコード値を返す.この方法をサポートすることは、ハッシュ・テーブルにいくつかの利点を提供することであり、例えば、java.util.Hashtableによって提供されるハッシュ・テーブルである.
equalsを書き換えない場合、比較はオブジェクトの参照が同じメモリアドレスを指すかどうかであり、書き換え後の目的は2つのオブジェクトのvalue値が等しいかどうかを比較することであることを知っています.特に、この場合、equalsを用いて8つのパッケージオブジェクト(int,floatなど)とStringクラス(equalsとhashcodeメソッドが書き換えられているため)のオブジェクトを比較する場合、デフォルトでは値が比較され、他のオブジェクトを比較する際に比較の参照アドレスとなる.jdkでequalsを書き換える際にhashcodeを書き換える必要があるのかという問題が生じる.
hashcodeはハッシュデータへの高速アクセスであり、HashSet/HashMap/Hashtableクラスを利用してデータを格納する場合、格納対象のhashcode値に基づいて同じか否かを判断するものであると理解しています.このように、オブジェクトに対してeuqalsを書き換えると、オブジェクトのメンバー変数の値が等しい限りeuqalsはtrueに等しいがhashcodeを書き換えないという意味である、元のオブジェクトとして新しいオブジェクトをnewする.equals(新しいオブジェクト)がtrueに等しい場合、両者のhashcodeは異なるため、ハッシュセットを格納する場合(Setクラスなど)、2つの値の同じオブジェクトが格納されて混同するため、hashcodeも書き換える必要がある.この一致を保証するためには、以下の2つの条件を満たさなければならない.
(1)obj 1.equals(obj 2)がtrueの場合、obj 1.hashCode() == obj2.hashCode()は、obj 1の場合true(2)でなければならない.hashCode() == obj2.hashCode()がfalseの場合、obj 1.equals(obj 2)はfalseでなければなりません
以下、簡単な例で検証します.
import java.util.*;
class BeanA {
private int i;
public BeanA(int i) {
   this.i = i;
}
public String toString() {
   return "   " + i;
}
public boolean equals(Object o) {
   BeanA a = (BeanA) o;
   return (a.i == i) ? true : false;
}
public int hashCode() {
   return i;
}
}
public class HashCodeTest {

public static void main(String[] args) {
   HashSet set = new HashSet();
   for (int i = 0; i <= 3; i++){
    set.add(new BeanA(i));
   }
   System.out.println(set);
   set.add(new BeanA(1));
   System.out.println(set.toString());
   System.out.println(set.contains(new BeanA(0)));
   System.out.println(set.add(new BeanA(1)));
   System.out.println(set.add(new BeanA(4)));
   System.out.println(set);
}
}

クラスBeanAでequalsメソッドとhashcodeメソッドを書き換え、HashSetデータセットに格納すると、重複するデータが発生しないことを保証します.この2つのメソッドを削除すると、重複するデータがHashSetに格納されます.これはHashSetが強調した要素の一意性とは異なり、この2つのメソッドを注釈して実行することができます.
したがって、いくつかのjavaクラスでequalsとhashcodeを書き換える必要がある場合を理解することができます.たとえばhibernateのエンティティクラスでは、データベースのローを1つのプライマリ・キー(または一意の識別子)で判断することが多いため、この2つのメソッドを書き換える必要があります.Hibernateは、特定のセッションの範囲内でのみ識別を永続化することを保証します.(データベースの行)とJava識別子は等価です.したがって、異なるセッションから取得したインスタンスをブレンドすると、Setに明確な意味がある場合はequals()とhashCode()を実装する必要があります.