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