扩容:
void resize(int newCapacity){
Entry [] oldTavle = table;
int oldCapacity = oldTable.length;
if(oldCapacity == MAXIMUM_CAPACITY){
threshold = Integer.MAX_VALUE;
return;
}
Entry [] newTable = new Entry[newCapacity];
transfer(newTable,initHashSeedAsNeeded(newCapacity));//将老的数组中的元素转移到新的数组中
table = newTable;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
}
转移
void transfer(Entry[] newTable,boolean rehash){
int newCapacity = newTable.length;
for(Entry<K,V> e : table){
while(null != e){
Entry<K,V> next = e.next;
if(rehash){
//得到hash值
e.hash = null == e.key ? 0 : hash(e.key);
}
//重新计算数组索引
int i = indexFor(e.hash,newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
核心代码
void transfer(Entry[] newTable,boolean rehash){
int newCapacity = newTable.length;
//循环就的table数组
for(Entry<K,V> e : table){
//判断当前位置下的结点,并移动
while(null != e){
Entry<K,V> next = e.next;
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
核心代码图解
在单线程时:
------------------------------------------- 以上是while循环的第一次完成-------------------------------------------
------------------------------------------- 以上是while循环的第二次完成-------------------------------------------
再次判断e==null,所以跳出while循环
------------------------------------------- 以上是最终在新的数组中的样子------------------------------------------
在多线程时:(会出现环形链表)
由于线程1挂起,线程2操作(线程2的操作可以参照在单线程的操作)得到下图结果
当线程2操作完成后线程1醒了,又开始了挂起之后的操作:
------------------------------------------- 执行完成发现形成了循环链表------------------------------------------
------------------------------------------- 以上是最终在新的数组中的样子------------------------------------------