Java でハッシュコード関数をオーバーライドする
Java の hashcode は、ハッシュアルゴリズムを使用し、オブジェクトを表す整数値を返す関数です。hashcode() は Object クラスの一部です。つまり、この関数は Object クラスを継承するすべてのクラスで使用できます。
この記事では、hashcode() メソッドをオーバーライドして実装を提供する方法を説明します。
hashcode() メソッドをオーバーライドする理由
hashcode() 関数をオーバーライドする前に、このメソッドをオーバーライドする必要がある理由を理解する必要があります。覚えておくべき重要なことは、メソッド equals() と hashcode() が一緒になり、equals() 関数がオーバーライドされるたびに hashcode() メソッドをオーバーライドすることが一般的に必須であるということです。hashcode() は、オブジェクトが等しい場合、それらのハッシュコードも等しくなければならないことを示しているためです。
hashcode() メソッドをオーバーライドする動機を実際に理解するために、HashCodeExample と DummyClass という 2つのクラスを使用して例を作成します。DummyClass では、abc 変数を設定する単純なコンストラクターを提供します。ここで、HashCodeExample クラスで、DummyClass クラスの 2つのインスタンスを作成し、コンストラクターで同じ値を持つ dummyClass1 と dummyclass2 という名前を付けます。
equals() メソッドを使用して 2つのインスタンスを比較しますが、出力はそれらが等しくないことを示しています。
public class HashCodeExample {
public static void main(String[] args) {
DummyClass dummyClass1 = new DummyClass(10);
DummyClass dummyClass2 = new DummyClass(10);
System.out.println(dummyClass1.equals(dummyClass2));
}
}
class DummyClass {
int abc;
public DummyClass(int abc) {
this.abc = abc;
}
}
出力:
false
これは、Java のすべてのオブジェクトインスタンスに一意のハッシュコードが与えられているために発生します。このハッシュコードは、両方のオブジェクトで hashCode() メソッドを呼び出すことで確認できます。出力は、両方のオブジェクトの整数値が異なることを示しています。
System.out.println(dummyClass1.hashCode());
System.out.println(dummyClass2.hashCode());
出力:
2065951873
1791741888
等しくないオブジェクトの問題を修正するために、equals() 関数をオーバーライドして実装を使用できます。次のコードは最初のプログラムと同じですが、引数として Object を取り、boolean を返す equals() メソッドをオーバーライドします。
equals() 関数では、Object 型のパラメータ o を DummyClass のインスタンスを返す DummyClass 型としてキャストします。次に、DummyClass クラスの変数 abc を、メソッドで引数として渡されるオブジェクトの変数 abc と比較します。
出力は、インスタンスの値が同じ場合に true を返すようにデフォルトの実装を変更したため、dummyClass1.equals(dummyClass2) の結果が true になることを示しています。
public class HashCodeExample {
public static void main(String[] args) {
DummyClass dummyClass1 = new DummyClass(10);
DummyClass dummyClass2 = new DummyClass(10);
System.out.println(dummyClass1.equals(dummyClass2));
}
}
class DummyClass {
int abc;
public DummyClass(int abc) {
this.abc = abc;
}
@Override
public boolean equals(Object o) {
DummyClass dummyClassObj = (DummyClass) o;
return this.abc == dummyClassObj.abc;
}
}
出力:
true
上記のソリューションは、オブジェクト dummyClass1 と dummyClass2 の両方のハッシュコードがまだ異なるため、ハッシュコードではなく値を比較する場合にのみ機能します。
よりわかりやすく説明するために、Set<DummyClass> タイプのオブジェクトを返す HashSet() を作成し、add() 関数を使用して両方の DummyClass オブジェクトを追加します。ここで、Set を出力し、出力で異なる参照を持つ 2つのオブジェクトを取得します。これは、DummyClass オブジェクトが異なるハッシュコードを持っていることを証明します。
ここで、hashcode() 関数をオーバーライドして問題を修正します。これは、次の例で確認できます。
import java.util.HashSet;
import java.util.Set;
public class HashCodeExample {
public static void main(String[] args) {
DummyClass dummyClass1 = new DummyClass(10);
DummyClass dummyClass2 = new DummyClass(10);
Set<DummyClass> dummyClassSet = new HashSet<>();
dummyClassSet.add(dummyClass1);
dummyClassSet.add(dummyClass2);
System.out.println(dummyClassSet);
}
}
class DummyClass {
int abc;
public DummyClass(int abc) {
this.abc = abc;
}
@Override
public boolean equals(Object o) {
DummyClass dummyClass = (DummyClass) o;
return this.abc == dummyClass.abc;
}
}
出力:
[DummyClass@7b23ec81, DummyClass@6acbcfc0]
Java で hashcode() メソッドをオーバーライドする
hashcode() メソッドで実装を使用するには、最初に DummyClass クラスの hashcode() メソッドをオーバーライドし、クラスの変数 abc の値を返します。これで、ハッシュコードが abc の値に置き換えられます。ここで、dummyClassSet を出力すると、ハッシュコードまたは参照が同じであるため、オブジェクトは 1つだけ取得されます。
import java.util.HashSet;
import java.util.Set;
public class HashCodeExample {
public static void main(String[] args) {
DummyClass dummyClass1 = new DummyClass(10);
DummyClass dummyClass2 = new DummyClass(10);
Set<DummyClass> dummyClassSet = new HashSet<>();
dummyClassSet.add(dummyClass1);
dummyClassSet.add(dummyClass2);
System.out.println(dummyClassSet);
}
}
class DummyClass {
int abc;
public DummyClass(int abc) {
this.abc = abc;
}
@Override
public boolean equals(Object o) {
DummyClass dummyClass = (DummyClass) o;
return this.abc == dummyClass.abc;
}
@Override
public int hashCode() {
return abc;
}
}
出力:
[DummyClass@a]
オブジェクト dummyClass1 と dummyClass2 の両方のハッシュコードを出力すると、同じハッシュコードが得られます。
System.out.println(dummyClass1.hashCode());
System.out.println(dummyClass2.hashCode());
出力:
10
10
Rupam Saini is an android developer, who also works sometimes as a web developer., He likes to read books and write about various things.
LinkedIn