web-dev-qa-db-ja.com

JavaのhashCode()メソッドはどのように機能しますか?

オブジェクトAPIの hashCode() メソッドを使用してJavaがハッシュ値を生成する方法に興味がありますか?

17
Hellnar

JavaはhashCode()を生成しません。つまり、ここでは自動化は行われません。ただし、Objectは、オブジェクトのインスタンスのメモリアドレスに基づいてHashCodeを生成します。ほとんどのクラス(特にCollection AP​​Iのいずれかで使用する場合)は、独自のHashCodeを実装する必要があります(契約により、独自のequalsメソッドを実装する必要があります)。

10
MarkPowell

ObjecthashCode()は実際にはネイティブメソッドであり、実装は実際には純粋なJavaではありません。さて、それがどのように機能するかに関して、 トムホーティンからのこの答え はそれを説明するのに素晴らしい仕事をします:

多くの人がObject.hashCodeは、メモリ内のオブジェクト表現のアドレスを返します。最新の実装では、オブジェクトは実際にはメモリ内を移動します。代わりに、オブジェクトヘッダーの領域を使用して値を格納します。値は、値が最初に要求されたときのメモリアドレスから遅延して導出される場合があります。

答え全体は実際に読む価値があります。

24
Pascal Thivent

Java Platform APIのドキュメントによると、ハッシュコードの計算はオブジェクトの32ビット内部JVMアドレスに基づいています。

実行中にオブジェクトが移動するのは事実です(唯一の理由はガベージコレクターです)。ただし、ハッシュコードは変更されません。

だからあなたがこのようなオブジェクトを持っているとき

Person person1 = new Person();
person1.setName("Alex");

Person person2 = new Person();
person2.setName("Alex");

Person person3 = person2;

この場合、これら2つのオブジェクトのメモリアドレスが同じではないため、person1.hashCodeはperson2.hashCodeと等しくなりません。

ただし、person2.hashCodeは同じオブジェクトを指しているため、person3と同じになります。

したがって、オブジェクトにhashCodeメソッドを使用する必要がある場合は、自分で実装する必要があります。

ちなみにString.hashCodeの実装は異なります。これは次のようなものです:(C#構文)

public int hashCode(String str)
{
  int h = 0;

  for (int i = 0; i < str.Length; i++)
    h = (h * 31) + str[i];

  return h;
}

edit:ここではオーバーフローチェックが行われないため、hashCodeは正または負の場合があります。

5
JCasso

Object.hashCode()は、特定のオブジェクトのID番号に基づくSystem.identityHashCode()を使用します。

4
Peter Lawrey

HashCode()関数には、ハッシュコードを作成するためのいくつかのオプションがあります。 JVM起動パラメータを設定します。 C++で記述されたhashCode()を作成する関数で、コードを見ることができます ここ

  • HashCode == 0:オブジェクトがメモリ内のどこにあるかとは関係なく、単に乱数を返します。私の知る限り、シードのグローバルな読み取り/書き込みは、プロセッサが多数あるシステムには最適ではありません。
  • HashCode == 1:ハッシュコード値をカウントアップします。どの値で開始するかはわかりませんが、かなり高いようです。
  • HashCode == 2:常にまったく同じIDハッシュコード1を返します。これは、オブジェクトIDに依存するコードをテストするために使用できます。上記の例でJavaChampionTestがKirkのURLを返した理由は、すべてのオブジェクトが同じハッシュコードを返していたためです。
  • HashCode == 3:ハッシュコード値をゼロからカウントアップします。スレッドセーフではないように見えるため、複数のスレッドが同じハッシュコードでオブジェクトを生成する可能性があります。
  • HashCode == 4:これは、オブジェクトが作成されたメモリの場所と何らかの関係があるようです。
  • HashCode> = 5:これはJava 8のデフォルトのアルゴリズムであり、スレッドごとのシードがあります。疑似乱数を生成するためのMarsagliaのxor-shiftスキーム。

情報は ここ から取得されました

2
Denis Stepanov

Javaはあなたにとって意味のあるhashCodeを生成しません。有用なhashCodeを生成するのはプログラマーとしてのあなたの仕事です。デフォルトのhashCodeは単なるメモリ位置です。

1
fastcodejava

hashCodeメソッドは数値を出力します。オブジェクトが変更されない場合、オブジェクトのハッシュコードは常に同じです。一意である必要はないことを言及することが重要です。

HashCode()のデフォルトの実装は、オブジェクトのアドレスに基づいてオブジェクトのハッシュコード番号を返すように指定されています。 JVMは、オブジェクトのアドレスに基づいてこの一意の番号を自動的に生成します。

2つのオブジェクトが同じメモリ位置にある場合(2つの参照変数によって参照される同じオブジェクト)、両方のハッシュコード番号は同じになりますが、2つのオブジェクトが異なるメモリ位置にある場合、両方のオブジェクトのハッシュコード番号は異なります。

メソッドをオーバーライドする必要があるため、おそらく質問をしました。しかし、いつそれをオーバーライドするのですか?

HashCode()メソッドのデフォルトの実装は、オブジェクトのアドレスに基づいてハッシュコード番号(オブジェクトの一意のID)を返します。しかし、アプリケーションが(オブジェクトのアドレスではなく)いくつかの異なるパラメーターに基づいてオブジェクトを一意に識別する必要がある場合は、hashCode()メソッドをオーバーライドし、要件に従って実装を行う必要があります。

トピックに関するEffective Javaからの重要なメモ:

enter image description here

詳細については、これをチェックしてください Javaハッシュコードの例

0
Johnny