2016-10-19 1 views
1

Wikiでは、アイテムを辞書に追加するたびに(GetHashCodeを呼び出すことによって)ハッシュコードが計算されることを伝えています。システムは次に、ハッシュコードを使用して、自分の値が保存されるバケットを見つけます。辞書のキーハッシュコードと値が格納されているバケットのインデックスとの関係

私の値が辞書に格納されるバケット配列のハッシュコードとインデックスの関係を見つけるロジックを教えてください。

私がGetHashCodeメソッド誰Dictiornaryを作成し、それにオブジェクトを追加するときの状況を想像してみては値1000000

を返し、それは辞書内の1000000個の要素を持つ配列を作成し、インデックス999999999で私のオブジェクトを格納することを意味するのでしょうか?

これが正しいとすれば、1つの値だけを格納するような大きなサイズの配列を持つ点は何でしょうか。

+0

関係が文書化されていないため、CLIの更新によって変更される可能性があります。さまざまなツールを使用すると、アセンブリの逆コンパイルが可能になります。しかし、特定のものに依存すると、ランダムな破損の可能性があります。これはXY問題のように聞こえるので、なぜ知りたいのですか? – Richard

+0

いいえインデックスは、ハッシュコードとテーブルサイズの組み合わせ(たとえば、 'hashCode%table.Count')と衝突を解決した結果から計算されます。実装[ここ](https://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs,fd1acf96113fbda9)を見ることができます – Lee

+0

概念的には、ハッシュバケット*は、所定のインデックスまたはインデックス範囲の値を格納することができる。必ずしも直接的な物理ストレージにマップする必要はありません。 「位置の配列」として実装することもできます。実装がデフォルトのバケット10個を提供する場合、キー/値のペアがあれば、各バケットはリンクされたリストに過ぎません。 –

答えて

2

あなたの前提は正しくない、運良くありません。そうであれば、実際にはバケットではなく、単にインデックスにアクセスできるオブジェクトの配列になります。あなたのハッシュコードが一意であることが保証されている場合、O(1)ルックアップでうまくいくかもしれませんが、そうではありません。実際には、ではなく、が一意であることが保証されています。 Int64のすべての可能な値を一意のInt32ハッシュコードにマップすることはできません。それはハッシュコードのためではありません。

代わりに、辞書は小さなバケットの配列を初期化し、単純なモジュロ演算を使用してバケットを検索します。 (.NET Reference Sourceから)

int targetBucket = hashCode % buckets.Length; 

あなたのハッシュアルゴリズムがうまくその仕事をしている場合、それはハッシュコード意味10個のバケットが存在する場合、例えば、それは10でハッシュコードを割った余りを取得することを意味つまり、nの項目は、十分に大きな値のnで、バケット間で均等に分割されます。

初期化されるバケットの数は、ctorで渡された容量よりも大きい最初の素数または0(See here)になります。これによりハッシュ衝突が多すぎると、自動的に展開され、安定するまで次の素数にジャンプします。

関連する問題