web-dev-qa-db-ja.com

Java Array HashCode implementation

これは奇妙です。同僚が、JavaでのmyArray.hashCode()の実装について尋ねました。私は知っていたと思ったが、その後、いくつかのテストを実行した。以下のコードを確認してください。私が気づいた奇妙な考えは、最初のシステムを書いたとき、結果が異なっていたということです。メモリアドレスを報告し、クラスを変更してアドレスまたは何かを移動したようなものです。ただ共有すると思った。

int[] foo = new int[100000];
Java.util.Random Rand = new Java.util.Random();

for(int a = 0; a < foo.length; a++) foo[a] = Rand.nextInt();

int[] bar = new int[100000];
int[] baz = new int[100000];
int[] bax = new int[100000];
for(int a = 0; a < foo.length; a++) bar[a] = baz[a] = bax[a] = foo[a];

System.out.println(foo.hashCode() + " ----- " + bar.hashCode() + " ----- " + baz.hashCode() +  " ----- " + bax.hashCode());

// returns 4097744 ----- 328041 ----- 2083945 ----- 2438296
// Consistently unless you modify the class.  Very weird
// Before adding the comments below it returned this:
// 4177328 ----- 4097744 ----- 328041 ----- 2083945


System.out.println("Equal ?? " +
  (Java.util.Arrays.equals(foo, bar) && Java.util.Arrays.equals(bar, baz) &&
  Java.util.Arrays.equals(baz, bax) && Java.util.Arrays.equals(foo, bax)));
49
souLTower

Java.lang.ArrayhashCodeメソッドはObjectから継承されます。つまり、ハッシュコードは参照に依存します。配列の内容に基づいてハッシュコードを取得するには、Arrays.hashCodeを使用します。

ただし、浅いハッシュコードの実装に注意してください。 Arrays.deepHashCodeの深い実装も存在します。

89
MahdeTo

配列はデフォルトのハッシュコードを使用します。これはメモリの場所に基づいています(ただし、intのみであり、すべてのメモリアドレスが収まらないため、必ずしもtheメモリの場所とは限りません)。これは、System.identityHashCode(foo)の結果も出力することで確認できます。

配列は、それらが同じ同一の配列である場合にのみequalです。したがって、配列ハッシュコードは、一般に、同じ配列である場合にのみ等しくなります。

4
erickson

Object.hashCode()のデフォルトの実装は、実際にはオブジェクトのポインター値を返すことですが、これは実装に依存します。たとえば、64ビットJVMはポインターとXORおよび高次と低次の単語を一緒に使用できます。サブクラスは、適切な場合、この動作をオーバーライドすることをお勧めします。

ただし、可変配列で等値比較を実行することは意味がありません。要素が変更されると、2つは等しくなくなります。同じ配列がその要素に何が起こっても常に同じhashCodeを返すという不変条件を維持するために、配列はデフォルトのハッシュコードの動作をオーバーライドしません。

Java.util.Arraysは、配列自体のIDではなく、配列の内容に基づいてハッシュすることが重要な場合に、deepHashCode()実装を提供することに注意してください。

1
James

Java.util.Arrays.hashCode(またはgoogle guavaジェネリックラッパーObjects.hashcode)の使用に同意しますが、Terracottaを使用している場合、これが問題を引き起こす可能性があることに注意してください- このリンク を参照してください

1
Carl Pritchett