然后該執(zhí)行 key(3)的 next 節(jié)點(diǎn) key(7)了:
現(xiàn)在的 e 節(jié)點(diǎn)是 key(7),首先執(zhí)行 Entry<k,v> next = e.next ,那么 next 就是 key(3)了
執(zhí)行 e.next = newTable[i] ,于是key(7) 的 next 就成了 key(3)
執(zhí)行 newTable[i] = e ,那么線(xiàn)程1的新 Hash 表第一個(gè)元素變成了 key(7)
執(zhí)行 e = next ,將 e 指向 next,所以新的 e 是 key(3)
這時(shí)候的狀態(tài)圖為:

然后又該執(zhí)行 key(7)的 next 節(jié)點(diǎn) key(3)了:
現(xiàn)在的 e 節(jié)點(diǎn)是 key(3),首先執(zhí)行 Entry<k,v> next = e.next ,那么 next 就是 null
執(zhí)行 e.next = newTable[i] ,于是key(3) 的 next 就成了 key(7)
執(zhí)行 newTable[i] = e ,那么線(xiàn)程1的新 Hash 表第一個(gè)元素變成了 key(3)
執(zhí)行 e = next ,將 e 指向 next,所以新的 e 是 key(7)
這時(shí)候的狀態(tài)如圖所示:

很明顯,環(huán)形鏈表出現(xiàn)了!!當(dāng)然,現(xiàn)在還沒(méi)有事情,因?yàn)橄乱粋€(gè)節(jié)點(diǎn)是 null,所以transfer() 就完成了,等 put() 的其余過(guò)程搞定后,HashMap 的底層實(shí)現(xiàn)就是線(xiàn)程1的新 Hash 表了。
2. fail-fast
如果在使用迭代器的過(guò)程中有其他線(xiàn)程修改了map,那么將拋出ConcurrentModificationException,這就是所謂fail-fast策略。
這個(gè)異常意在提醒開(kāi)發(fā)者及早意識(shí)到線(xiàn)程安全問(wèn)題,具體原因請(qǐng)查看 ConcurrentModificationException的原因以及解決措施
順便再記錄一個(gè)HashMap的問(wèn)題:
為什么String, Interger這樣的wrapper類(lèi)適合作為鍵?String, Interger這樣的wrapper類(lèi)作為HashMap的鍵是再適合不過(guò)了,而且String最為常用。因?yàn)镾tring是不可變的,也是final的,而且已經(jīng)重寫(xiě)了equals()和hashCode()方法了。其他的wrapper類(lèi)也有這個(gè)特點(diǎn)。不可變性是必要的,因?yàn)闉榱艘?jì)算hashCode(),就要防止鍵值改變,如果鍵值在放入時(shí)和獲取時(shí)返回不同的hashcode的話(huà),那么就不能從HashMap中找到你想要的對(duì)象。不可變性還有其他的優(yōu)點(diǎn)如線(xiàn)程安全。如果你可以?xún)H僅通過(guò)將某個(gè)field聲明成final就能保證hashCode是不變的,那么請(qǐng)這么做吧。因?yàn)楂@取對(duì)象的時(shí)候要用到equals()和hashCode()方法,那么鍵對(duì)象正確的重寫(xiě)這兩個(gè)方法是非常重要的。如果兩個(gè)不相等的對(duì)象返回不同的hashcode的話(huà),那么碰撞的幾率就會(huì)小些,這樣就能提高HashMap的性能。