Java でハッシュコード関数をオーバーライドする

Rupam Yadav 2023年10月12日
  1. hashcode() メソッドをオーバーライドする理由
  2. Java で hashcode() メソッドをオーバーライドする
Java でハッシュコード関数をオーバーライドする

Java の hashcode は、ハッシュアルゴリズムを使用し、オブジェクトを表す整数値を返す関数です。hashcode()Object クラスの一部です。つまり、この関数は Object クラスを継承するすべてのクラスで使用できます。

この記事では、hashcode() メソッドをオーバーライドして実装を提供する方法を説明します。

hashcode() メソッドをオーバーライドする理由

hashcode() 関数をオーバーライドする前に、このメソッドをオーバーライドする必要がある理由を理解する必要があります。覚えておくべき重要なことは、メソッド equals()hashcode() が一緒になり、equals() 関数がオーバーライドされるたびに hashcode() メソッドをオーバーライドすることが一般的に必須であるということです。hashcode() は、オブジェクトが等しい場合、それらのハッシュコードも等しくなければならないことを示しているためです。

hashcode() メソッドをオーバーライドする動機を実際に理解するために、HashCodeExampleDummyClass という 2つのクラスを使用して例を作成します。DummyClass では、abc 変数を設定する単純なコンストラクターを提供します。ここで、HashCodeExample クラスで、DummyClass クラスの 2つのインスタンスを作成し、コンストラクターで同じ値を持つ dummyClass1dummyclass2 という名前を付けます。

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 型のパラメータ oDummyClass のインスタンスを返す 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

上記のソリューションは、オブジェクト dummyClass1dummyClass2 の両方のハッシュコードがまだ異なるため、ハッシュコードではなく値を比較する場合にのみ機能します。

よりわかりやすく説明するために、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]

オブジェクト dummyClass1dummyClass2 の両方のハッシュコードを出力すると、同じハッシュコードが得られます。

System.out.println(dummyClass1.hashCode());
System.out.println(dummyClass2.hashCode());

出力:

10
10
著者: Rupam Yadav
Rupam Yadav avatar Rupam Yadav avatar

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