CLRS (「アルゴリズム入門」) という本には、mod、multiply などのハッシュ関数がいくつか記載されています。
Java はキーをスロットにマッピングするためにどのハッシュ関数を使用しますか?
ここに質問があるのを見ましたJava言語で使用されるハッシュ関数しかし、それは質問への答えではなく、その質問に対するマークされた答えは間違っていると思います。hashCode() を使用すると、Hashtable に対して独自のハッシュ関数を実行できると書かれていますが、それは間違っていると思います。
hashCode() によって返される整数は Hashtble の実際のキーであり、Hashtable はハッシュ関数を使用して hashCode() をハッシュします。この回答が意味するのは、Java では Hashtable にハッシュ関数を与える機会が与えられるということですが、それは間違いです。hashCode() はハッシュ関数ではなく実際のキーを与えます。
では、Java は具体的にどのようなハッシュ関数を使用するのでしょうか?
ベストアンサー1
OpenJDK の HashMap にキーが追加されたり、HashMap からキーが要求されたりする場合、実行フローは次のようになります。
- キーは、開発者が定義した方法を使用して 32 ビット値に変換されます
hashCode()
。 - 32ビットの値は、2番目のハッシュ関数(Andrew の回答にはソース コードが含まれています) をハッシュ テーブル内のオフセットに挿入します。この 2 番目のハッシュ関数は HashMap の実装によって提供され、開発者がオーバーライドすることはできません。
- ハッシュ テーブルの対応するエントリには、リンク リストへの参照が含まれます。キーがハッシュ テーブルにまだ存在しない場合は、null が含まれます。衝突がある場合 (同じオフセットを持つ複数のキー)、キーとその値は、単一のリンク リストに単純に収集されます。
ハッシュテーブルのサイズが適切に大きく選ばれると、衝突の回数は制限されます。したがって、1回の検索には平均して一定の時間しかかかりません。これを予想される定数時間ただし、攻撃者がハッシュ テーブルに挿入されたキーを制御し、使用されているハッシュ アルゴリズムに関する知識を持っている場合、ハッシュ衝突を多数引き起こして、線形検索時間を強制することができます。そのため、最近、ハッシュ テーブルの実装の一部が変更され、どのキーが衝突を引き起こすかを攻撃者が予測しにくくするランダム要素が含まれるようになりました。
いくつかのASCIIアート
key.hashCode()
|
| 32-bit value
| hash table
V +------------+ +----------------------+
HashMap.hash() --+ | reference | -> | key1 | value1 | null |
| |------------| +----------------------+
| modulo size | null |
| = offset |------------| +---------------------+
+--------------> | reference | -> | key2 | value2 | ref |
|------------| +---------------------+
| .... | |
+----------------+
V
+----------------------+
| key3 | value3 | null |
+----------------------+