こんにちは。「Javaを復習する初心者」です。
今回はEclipseでObject#hashCodeメソッドの実装を自動生成してみました。
hashCodeメソッド
EclipseではフィールドからObject#hashCodeメソッドを自動生成する機能があります。今回はint a, int bをフィールドに持つクラスを作成し、Eclipseで自動生成してみました。以下のようなソースが自動生成されました。
ソースコード
package objectTest;
public class HashCodeAuto {
public int a;
public int b;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + a;
result = prime * result + b;
return result;
}
}
実装の規則
hashCodeメソッドは以下の規則で実装する必要があります。API仕様書にある「public int hashCode()」の解説を要約すると以下の3つの規則があります。
- hashCodeメソッドは常に同じ整数を返す。
- 2つのオブジェクトが等しい場合、同じ整数を返す。
- 2つのオブジェクトが等しくない場合は、異なる整数の結果が生成される必要ない。
一つ目の規則は最初はよくわかりませんでしたが、例えばRandomクラスで乱数を使った場合、規則から外れることになるのでしょう。3つ目がポイントだと思います。hashCodeメソッドの返却値でオブジェクトがグループ化されれば良いということなのでしょう。なので同じ値を持つフィールドの値の合わせがあっても良いことになります。
Eclipseで生成されたメソッドも返却値が重複するということを今回は調べてみました。以下、具体的な値での実験です。b=0のとき、aが0から9まで、a=0のとき、bが31から40までhashCodeを出力するプログラムを書きました。
以下はソースと実行結果です。
ソースコード
package objectTest;
public class HashCodeAutoTest {
public static void main(String[] args) {
HashCodeAuto h = new HashCodeAuto();
h.b = 0;
for (int i = 0; i < 10; i++) {
h.a = i;
System.out.println(h.a + ", " + h.b + "; " + h.hashCode());
}
h.a = 0;
for (int i = 0; i < 10; i++) {
h.b = 31 + i;
System.out.println(h.a + ", " + h.b + "; " + h.hashCode());
}
}
}
結果
0, 0; 961
1, 0; 992
2, 0; 1023
3, 0; 1054
4, 0; 1085
5, 0; 1116
6, 0; 1147
7, 0; 1178
8, 0; 1209
9, 0; 1240
0, 31; 992
0, 32; 993
0, 33; 994
0, 34; 995
0, 35; 996
0, 36; 997
0, 37; 998
0, 38; 999
0, 39; 1000
0, 40; 1001
hashCodeが重複するパターンがあるのが上記結果から読み取れました。「a=0, b=0」のときと「a=0, b=31」が同じ値になります。
重複が多くなる例
自動生成されるprimeの値を2にすると重複が多くなります。
以下はソースと実行結果です。
ソースコード
package objectTest;
public class HashCodeCustom {
public int a;
public int b;
@Override
public int hashCode() {
final int prime = 2;
int result = 1;
result = prime * result + a;
result = prime * result + b;
return result;
}
}
package objectTest;
public class HashCodeCustomTest {
public static void main(String[] args) {
HashCodeCustom h = new HashCodeCustom();
for (int i = 0; i < 10; i++) {
h.a = i;
for (int j = 0; j < 10; j ++) {
h.b = j;
System.out.printf("%2d ", h.hashCode());
}
System.out.println();
}
}
}
結果
4 5 6 7 8 9 10 11 12 13
6 7 8 9 10 11 12 13 14 15
8 9 10 11 12 13 14 15 16 17
10 11 12 13 14 15 16 17 18 19
12 13 14 15 16 17 18 19 20 21
14 15 16 17 18 19 20 21 22 23
16 17 18 19 20 21 22 23 24 25
18 19 20 21 22 23 24 25 26 27
20 21 22 23 24 25 26 27 28 29
22 23 24 25 26 27 28 29 30 31
a, bそれぞれ0から9の表を出力してみました。重複が多いのが分かります。