以下の分析に基づいてJDK1.7。
示されるように、HashMapの基礎となる配列は、リンクされたリストに基づいて実装されています。2つの重要なパラメータがあります。
- 容量
- 荷重係数
場合容量のデフォルトサイズは、負荷率が0.75であり、16で膨張(体積と負荷率を自由に調節することができる)場合に発生することができます。HashMap
size > 16*0.75
putメソッド
キーは、最初の着信になりますhash
次に、ハッシュコードを計算するモジュロ配列の長さに応じて、インデックス配列内のインデックスを計算する動作を制御します。
アレイの所定の長さのHashMapであるように、モジュロ演算より高い中央値の計算の動作をより効率的に以来2^n
。従ってによって2^n - 1
同じビット算術モジュロ効果を行う、また、非常に高い効率。
この状況は、リンクされたリストを使用することによって解決することができる配列の限定された長さに起因するので、必然的に計算によって得られた異なるキーインデックスの同じがあるだろうが、HashMapのは、あろうtable[index]
補間データを用いて、頭部がリストに挿入され、リンクされたリストを形成します。
getメソッド
取得と同様に置くが、この位置はを通じて、リスト全体を横断するリンクリストが必要である場合、着信キー指数を算出し、key.equals(k)
対応する要素を見つけること。
トラバーサル
1 |
反復子<のMap.Entry <文字列、整数>> entryIterator = map.entrySet()反復子()。一方、(entryIterator.hasNext()){ のMap.Entry <文字列、整数>次= entryIterator.next()。 System.out.println("キー=" + next.getKey()+ "値=" + next.getValue())。 } |
1 |
反復子の<string>イテレータ= map.keySet()反復子()。一方、(iterator.hasNext()){ 文字列キー= iterator.next()。 System.out.println("キー=" +キー+ "値=" + map.get(キー))。 |
1 |
map.forEach((キー、値) - > { |
それを強くお勧めします最初のentrySetトラバースを使用します。
最初のキー値を同時に撮影することができ、我々はそれが第三の必要、非効率的な、キーによって第2の値を取る必要がありますJDK1.8
表リストを横断外側、内側または赤黒木を横断、以上。
通知
同時環境で使用されるHashMap
無限ループになりやすいです。
シーンは、場所の同時展開を取る呼び出すresize()
方法をrehash()
循環リンクリストになりやすい、時間。取得したときに、このような、存在しないkey
計算した場合index
とき、円形のリンクリストのインデックスだけで無限ループが発生しています。
HashMapのように、単一スレッドのみに使用され、可能な限り多くの削減プリセット容量拡張にしてみてください。
内JDK1.8
の中央HashMap
に最適化:
ときにhash
衝突が閾値を超えた後、リストの長さが書き込まれる(デフォルトは8である)、リストは、に変換される赤黒木。
仮定しhash
、配列が続いている非常に深刻な対立は、複雑さがある再時に、この時間は非常に長いリストを取りましたO(n)
。
赤黒木場合は、時間の複雑さがありますO(logn)
。
大幅にクエリの効率を向上させます。