通过分配好迁移的区间之后,开始对数据进行迁移。在看这段代码之前,先来了解一下原理
synchronized (f) {
//对数组该节点位置加锁,开始处理数组该位置的迁移工作
if (tabAt(tab, i) == f) {
// 再做一次校验
Node<K,V> ln, hn;
//ln表示低位,hn表示高位;接下来这段代码的作用是把链表拆分成两部分,0在低位,1在高位
if(fh >= 0) {// 下面部分代码原理点击这里
int runBit = fh & n;
Node<K,V> lastRun = f;
//遍历当前bucket的链表,目的是尽量重用Node链表尾部的一部分
for (Node<K,V> p = f.next; p != null; p = p.next) {
int b = p.hash & n;
if (b != runBit) {
runBit = b;
lastRun = p;
}
}
if (runBit == 0) {如果最后更新的runBit是0,设置低位节点
ln = lastRun;
hn = null;
}
else {//否则,设置高位节点
hn = lastRun;
ln = null;
}
//构造高位以及低位的链表
for (Node<K,V> p = f; p != lastRun; p = p.next) {
int ph = p.hash;
K pk = p.
key;
V pv = p.val;
if ((ph & n) == 0)
ln = new Node<K,V>(ph, pk, pv, ln);
else hn = new Node<K,V>(ph, pk, pv, hn);
}
setTabAt(nextTab, i, ln);
//将低位的链表放在i位置也就是不动setTabAt(nextTab, i + n, hn);
//将高位链表放在i+n位置
setTabAt(tab, i, fwd);
// 把旧table的hash桶中放置转发节点,表明此hash桶已经被处理
advance = true;
}
//红黑树的扩容部分暂时忽略
}