「致命的なエラー」でjdk1.7のHashMap:循環リスト
図jdk1.7のHashMap構成。
jdk1.7は+リンクリスト構造の配列です
jdk1.7バージョンでは、2つの大きな問題が存在します
-
ケースは、第1の補間サイクル鎖をもたらします
-
リストが長すぎる、それが減少し、効率の問い合わせにつながります
jdk1.8のために最適化されたjdk1.8バージョン
- 補間を使用してテール、除去は、円形のリストを発生します
- リストが長すぎるの後、赤黒木に、クエリの効率を向上させます
私は、特にブログの別の記事を参照してください。HashMapのそれを:あなたは本当にメーカーが質問に直面している知っていますか?
円形リストを作成
一方、マルチスレッドput
の呼び出し同時に場合、resize
循環リストにつながる可能性がある操作をこのように取り戻すための時間を作り、生成され、それが無限ループになります。以下、詳細どのように循環リスト形式。
リサイズ機能
アレイの拡張機能は、主な機能は、拡張後の新しい配列を作成することで、呼び出すtransfer
関数は新しい配列に配列内の古い要素を移行します
void resize(int newCapacity)
{
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
......
//创建一个新的Hash Table
Entry[] newTable = new Entry[newCapacity];
//将Old Hash Table上的数据迁移到New Hash Table上
transfer(newTable);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
伝達関数
転送ロジックは、古いアレイを横断し、実際に簡単であり、古いによってアレイ素子ヘッダ補間方法、アレイ内の新たな問題嘘への移行に対応する位置のヘッド補間。
void transfer(Entry[] newTable)
{
//src旧数组
Entry[] src = table;
int newCapacity = newTable.length;
for (int j = 0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e != null) {
src[j] = null;
do {
Entry<K,V> next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);//由于是链表,所以有个循环过程
}
}
}
static int indexFor(int h, int length){
return h&(length-1);
}
ここでは実用的な例です
//下面详细解释需要用到这部分代码,所以先标号,将一下代码分为五个步骤
do {
1、Entry<K,V> next = e.next;
2、int i = indexFor(e.hash, newCapacity);
3、e.next = newTab[i];
4、newTable[i] = e;
5、e= next;
} while(e != null)
-
始めます 容量が2に設定され、閾値がロードされます
-
スレッド そして、スレッド 閾値が1であるので、必要にコールするよう一方、要素を挿入する
resize
機能を拡張するための操作を -
スレッド まず、コードをブロックし
Entry<K,V> next = e.next;
たスレッドの後、 操作の拡張を実行した後 -
スレッドの後 サイクルの完了後、引き続き、目を覚まします
始めます 、 、次のコードの実装、 、
2、int i = indexFor(e.hash, newCapacity); 3、e.next = newTab[i]; 4、newTable[i] = e; 5、e= next; 1、Entry<K,V> next = e.next;
-
スレッド 第二サイクルの実施後
始めます 、 、次のコードが実行され、$ E \ rightarrow3 $、
2、int i = indexFor(e.hash, newCapacity); 3、e.next = newTab[i]; 4、newTable[i] = e; 5、e= next; 1、Entry<K,V> next = e.next;
-
エンドレスループを形成する第3のサイクルの実行スレッドT1、後
始めます 、 、次のコードを、
2、int i = indexFor(e.hash, newCapacity); 3、e.next = newTab[i]; 4、newTable[i] = e; 5、e= next; 1、Entry<K,V> next = e.next;