ransfer方法的作用是把原table的Node放到新的table中,使用的是头插法,也就是说,新table中链表的顺序和旧列表中是相反的,在HashMap线程不安全的情况下,这种头插法可能会导致环状节点。
其中的while循环描述了头插法的过程,这个逻辑有点绕,下面举个例子来解析一下这段代码。
假设原有table记录的某个链表,比如table[1]=3,链表为3–>5–>7,那么处理流程为:
/**
* Transfers all entries from current table to newTable.
*/
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; //注释1
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity); //注释2
e.next = newTable[i]; //注释3
newTable[i] = e; //注释4
e = next; //注释5
}
}
}
1,注释1:记录e.next的值。开始时e是table[1],所以e3,e.next5,那么此时next==5。
2,注释2,计算e在newTable中的节点。为了展示头插法的倒序结果,这里假设e再次散列到了newTable[1]的链表中。
3,注释3,把newTable [1]赋值给e.next。因为newTable是新建的,所以newTable[1]null,所以此时3.nextnull。
4,注释4,e赋值给newTable[1]。此时newTable[1]=3。
5,注释5,next赋值给e。此时e==5。
此时newTable[1]中添加了第一个Node节点3,下面进入第二次循环,第二次循环开始时e==5。
1,注释1:记录e.next的值。5.next是7,所以next==7。
2,注释2,计算e在newTable中的节点。为了展示头插法的倒序结果,这里假设e再次散列到了newTable[1]的链表中。
3,注释3,把newTable [1]赋值给e.next。因为newTable[1]是3(参见上一次循环的注释4),e是5,所以5.next==3。
4,注释4,e赋值给newTable[1]。此时newTable[1]==5。
5,注释5,next赋值给e。此时e==7。
此时newTable[1]是5,链表顺序是5–>3。
下面进入第三次循环,第二次循环开始时e==7。
1,注释1:记录e.next的值。7.next是NULL,所以next==NULL。
2,注释2,计算e在newTable中的节点。为了展示头插法的倒序结果,这里假设e再次散列到了newTable[1]的链表中。
3,注释3,把newTable [1]赋值给e.next。因为newTable[1]是5(参见上一次循环的注释4),e是7,所以7.next==5。
4,注释4,e赋值给newTable[1]。此时newTable[1]==7。
5,注释5,next赋值给e。此时e==NULL。
此时newTable[1]是7,循环结束,链表顺序是7–>5–>3,和原链表顺序相反。
参考:https://blog.csdn.net/lkforce/article/details/89521318