HashMapのは素人の言語

HashMapのデータ構造

  HashMapのは、アレイの本質プラスリンクされたリストで、デフォルトの長さの配列は、膨張の全長の75%が倍増される記憶素子、16です。map.put(キー、ヴァル)は、実際には、各インデックス上に均一なヒットする配列の長さを法ハッシュハッシュに基づいて、各インデックス位置は、アレイを充填します。ハッシュモジュロインデックスが同じ場合に保存されている要素のリストにデータリンクの構造、主題を維持するために、ハッシュマップを競合ハッシュを避けるために、二つの要素になります後しかし、物事はそうできるだけ完璧ではありません。リストの深さがnである場合は、必要なを取得し、アレイ上の速度の要素だけですぐに取得しますが、リスト上の要素は非常に時間がかかるを取得する場合でも、このGET(キー)は、問題があるだろうときそうjdk1.8最適化された実行時の複雑さはO(N)であり、リスト> = 8の長さは、赤黒木に変わります場合、元のデータ構造に赤黒木を追加することです。

  

なぜ、2の初期容量整数パワーなら

/ ** 
 *初期デフォルトの容量は、 -のべき乗でなければなりませんには、2つ。
 * / 
静的 最終 int型の DEFAULT_INITIAL_CAPACITY = 1 << 4; // AKA 16 

  これは、初期容量jdk8で、私たちのデフォルトの初期容量を伝える -でなければなりません2の累乗。しかし、我々は、HashMapの<文字列、文字列> =地図作成の新しい新しいのHashMap <文字列、文字列>(7 );ああ与えられていません。実際、2のパワーを初期化時に、次のコードは、私たちよりも価値以上に、それを初期化し、それに近いです。例えば、我々は、その初期値は8である、7を指定するので、我々は17の初期値が32で指定します。

/ ** 
 *能力について2つのターゲットサイズに対してAの電力を返す
 * / 
静的 最終 INT tableSizeFor(int型CAP){
     int型。1 -のn-CAP = ; 
    N - = N - >>> 1 |。; 
    N-| >>> = N-2 
    N - | = N - >>> 4。; 
    N- | = N - >>> 8。; 
    N- | = N - >>> 16 リターン(N <0)1:(?N - > = MAXIMUM_CAPACITY) ?MAXIMUM_CAPACITY:1 + N- ; 
} 
    
問題になるので、なぜそれについて有効にする必要がありjdk8?単にデフォルトの香りを使用しないでください?
    実際に、我々はソースにオープンにポイントは、それが次のターゲットを計算する演算により、ビットが実際に知っているであろう(キー、値)を入れて、そのような効率は、弾性率よりも高いです。もちろん、なぜこの初期の長さは整数であり、2つの電源は問題ではないが、長さは2の整数乗でない場合、これは天才jdk8あるので、次に、算術モジュロ演算と添字のビットのうち、異なるであろう。
静的最終int型のハッシュ(オブジェクトキー){ 
int型、H。
リターン(キー== nullの)?0:(H = key.hashCode())^(H >>> 16)。
}
/ ** 
 *ハッシュコード時間のインデックスを返します。
 * / 
静的 INT indexFor(INT H、int型の長さ){
     戻り H&(長さ- 1 )。
}

 HashMapの負荷率

    なぜ負荷率が0.75でありますか?時間の複雑さと空間の複雑さのバランスに関連する事実です。、充填することが困難であることが通常の状況下では、配列全体の拡大を埋めるために取らなければならないことを意味1に続いloadfactor、以来、確かにハッシュ衝突がたくさんあるでしょう、リストに結果が長すぎます。loadfactor 0.5場合は、アレイ拡張の半分を埋めるだけでなく、スペースの使用率が高くない持っています。そのため、妥協値は0.75を取ります

JDK8最適化されたデータ構造のハッシュマップ

   / ** 
     *ビン内のノードは、ポアソン分布に従う
     (* http://en.wikipedia.org/wiki/Poisson_distribution で)
     サイズ変更デフォルトのために平均で約0.5の*パラメータ
     大きな分散を有するが、0.75 *閾値以下のため
     *サイズ変更の粒度。分散を無視して、予想される
     リストのサイズkの*出現である(EXP(-0.5)* POW(0.5、K)/ 
     *階乗(K))。
     最初の値は:
     * 
     * 0:0.60653066 
     * 1:0.30326533 
     * 2:0.07581633 
     * 3:0.01263606 
     * 4:0.00157952 
     * 5:0.00015795 
     * 6:0.00001316 
     * 7:0.00000094 
     * 8:0.00000006 
     *詳細:。千万未満最後以内に1 
     * / 
  8の我々の鎖長は、赤黒木構造に変換されます。ソースはまた、コメントによると、これはに基づいている確率結論"ポアソン分布"を学ぶ、式(EXP(-0.5)* POW(0.5、K)であり、/ * 階乗(K))、およびAあなたが欲しい8リストの深さまでの深さ、そしてそれが唯一の0.00000006の確率なので、全体のハッシュマップのパフォーマンスのための赤黒ツリーデータ構造は大きな改善です。多くのブログは、彼らはセントの関係を持っていない行うための負荷率が間違っているポアソン分布を、満足させることであると述べました。

 HashMapのスレッド安全性の問題

[1 ]、時間を置くデータの不整合が生じます。
1.スレッド1を計算インデックスが槽の座標は、KEY-挿入することが望ましいのHashMapと値のペアを、今回は、CPUタイムスライスがブロック状態に排気されます。
2 スレッド2はそれだけでバケツのインデックスとスレッド1が同じだし、データの挿入が成功した場合の動作は、プットを実行して開始しました。
図3は、スレッド1が今再び実行するように起こされる前に、彼はまだ、リストの先頭を保持しているデータを挿入するには良い場所を計算し続けます。
4 。最後に、それが突然消えるにレコードを挿入し2スレッドにつながる、スレッド2挿入されたレコードをカバーしています。

[ 2 ]配列拡張セキュリティ問題
実際には新しい配列を生成することで膨張し、その後は再計算新しいアレイの前にキーに書かれました。複数のスレッドを同時に検出能力が必要とされるとき、最終的に一つだけのスレッドの割り当てが成功した。しかし、他のスレッドがすべて失われます

 。

 

おすすめ

転載: www.cnblogs.com/wlwl/p/11954343.html