1

これは基本的な質問か、この背後にある基本的なアイデアかもしれません。

HasTable がキーの実際のメモリ アドレスをハッシュとして使用できないのはなぜですか? または、キーのアドレスをハッシュして使用しますか?

キー(オブジェクト)のデフォルトは実際にはオブジェクトのメモリアドレスであるという投稿を見ましたがhashCode()、これは正しくないと思います。

そして、バケットアドレスは実際にはhash % number of existing buckets?という投稿を読みました。これも正しくありません。

誰かが明確にすることができますか?

4

6 に答える 6

8

クラスが をオーバーライドせずhashCode()、 からデフォルトの実装を継承するだけの場合java.lang.Object、典型的な JVM では、そのhashCode()は多かれ少なかれ、それへの内部ポインタになります。(明らかに、これがすべてではありません。なぜなら、の戻り値の型はhashCode()isintであり、これは 64 ビット JVM に対応しないからです。また、これらは物理メモリ位置への実際のポインターではありません。まず、OS が仮想アドレスから物理アドレスへのマッピングを処理するためです。 2 つ目は、JVM がそれを処理したとしても、ガベージ コレクターはオブジェクトに影響を与えることなく、あるヒープから別のヒープにオブジェクトを移動できるためhashCode()です。それでも、「内部メモリ アドレス」は適切な最初の概算です。)

ほとんどの JDK クラスがオーバーライドする理由は、常に「互換性」hashCode()を保ちたいからです。つまり、 の場合、 が必要です。(これは、たとえば、キーが 2 つの異なるインスタンスであるという理由だけで aに 2 つの異なるエントリを持たせたくないということを考えると理にかなっています。キーの元のインスタンスを手元に用意する必要はありません.2 つのキーが等しい場合、通常はそれらを等しいものとして扱いたいと考えています。)hashCode()equals()a.equals(b)a.hashCode() == b.hashCode()Map<String, Object>"abc"Stringmap.get("abc")

マップでポインターの等価性が本当に必要な場合はjava.util.IdentityHashMapclassを使用できます。

于 2012-11-06T19:10:41.470 に答える
3

デフォルトObject.hashCode()は厳密にはメモリアドレスではありませんが、巨大なメモリがない限り、JVM 内のすべてのオブジェクト間で一意であるため、「論理」アドレスと見なすことができます。

HashMap には限られた数のバケットがあり、各キーにはハッシュ コードに基づいて実際にバケットが割り当てられます。ハッシュ コードごとに 1 つのバケットはありません。そのため、2 つのオブジェクトのハッシュ コードが異なっていても、それらは同じバケットに格納される可能性があります。そのため、このような衝突を避けるために、hashCode を可能な限り適切に分散させることが重要です。

キーのシステム ID ハッシュ コード (つまり、 によって返されるハッシュ コードObject.hashCode()) を使用することは、ほとんどの場合望ましくありません。2 つのキーが同じオブジェクト インスタンスである場合ではなく、同じ情報を保持している場合はそれらを等しくしたいからです。たとえば、学生を SSN に基づいてマップに保存し、後で Web サービスまたはデータベースからこの学生の SSN を取得する場合、同じ STring インスタンスはありませんが、できるようにしたいと考えています。受け取った SSN を使用して、地図で生徒を見つけます。

于 2012-11-06T19:09:53.380 に答える
1

HashTable がキーの実際のメモリ アドレスをハッシュとして使用できないのはなぜですか?

キーの同等性が重要だからです。2 つのオブジェクトが「等しい」( one.equals(two)true を返す) 場合、ハッシュ コードも等しい ( one.hashCode() == two.hashCode()) 必要があります。

于 2012-11-06T19:08:39.763 に答える
1

デフォルトhashCode()はメモリアドレスではなく、「ID ハッシュ」です。

メモリ アドレスは変更される可能性がありますが、特定のインスタンスの ID は一定です。

于 2012-11-06T19:09:10.400 に答える
0

JavaSE api で hashCode と equals に対して定められた規則を破ることなく、最適であると思われる hashCode の任意の実装を使用できます。

ここで等号とハッシュコードのルールを確認してください: http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html

Collections ライブラリやその他の API は、このプロパティに大きく依存して独自の動作を実装しているため、これは重要です。

于 2012-11-06T19:08:23.377 に答える
0

メモリ アドレスは、オブジェクトの hashCode として使用しないでください (その equals メソッドが同一性の比較のみを実行する場合を除きます)。その理由はJavaDocに明示的に書かれています:

{@code equals(Object)} メソッドに従って 2 つのオブジェクトが等しい場合、2 つのオブジェクトのそれぞれに対して {@code hashCode} メソッドを呼び出すと、同じ整数結果が生成される必要があります。

equals メソッドが ID 比較のみを実行する場合、hashCode() と equals() の両方が同じオブジェクトに対してのみ等しいため、メモリ アドレスで十分です。

于 2012-11-06T19:10:45.577 に答える