一、概覽
HashMap的某個桶位如果存儲的是單向列表,當向這個桶位繼續插入一個元素的時候,這個桶位元素的數量超過
8時,單項列表會轉化為紅黑樹(同時是一個雙向列表,jdk1.8之后),且會先轉化為雙向列表:
二、轉化過程
1,運行如下程序,使map底層數組的某個桶位的單向列表”開始“轉化為紅黑樹
按道理,當map-put的元素超過 8*100 = 800時才會擴容數組,所以,當map.put(65, "65")時,table[1]的位置將會是:
此時,table[1]的元素數量(9個)超過8(TREEIFY_THRESHOLD),這個單向列表會被轉化為紅黑樹,但是受
這個數字的影響,數組的長度(現在為8)只有擴容到64之后,才會將單向列表會被轉化為紅黑樹;擴容的過程:參考(參考http:還沒寫好)。
當map.put(513, "513")時,table[1]的位置將會是:
此時,table[1]的元素數量(9個)超過8(TREEIFY_THRESHOLD),這個單向列表”將會“被轉化為紅黑樹。
2,單向列表轉化為紅黑樹
先轉化為雙向鏈表,雙向鏈表轉化為紅黑樹,參考:http:還沒有寫好;
jdk1.8 - HashMap源代碼如下紅框所示:
e:tab[1],是一條單向鏈表,如上面數組的那個示意圖,節點都是Node類型,隨着單向列表不斷的遞進,指向的當前單向列表的節點;
hd:head?頭部節點,雙向列表的頭部節點,節點是TreeNode類型;
tl:tail?尾部節點,雙向列表的尾部節點,節點是TreeNode類型;
p:e當前指向的單向列表的節點轉化為TreeNode類型后的節點;
2.1,Node和TreeNode的聯系與區別
Node:
TreeNode:,
TreeNode是Node的子類,也就是說TreeNode含有Node的所有屬性;
Node是一個含有next屬性的單向列表,TreeNode是一個含有next(繼承自Node)、prev屬性的雙向鏈表,同時TreeNode還是一個含有left、right、parent屬性的二叉樹,同時TreeNode還是一個含有boolean red屬性的紅黑樹(在二叉樹的基礎上)。
2.2,單向列表開始轉化為雙向鏈表
p的來源:
1,第一次循環
2,第二次循環
3,第三次循環
4,以此類推
總結下來,就是:
A、讓單向列表遞進,使用局部變量(中間變量)e指向遞進過程中的某個節點;
B、使用中間變量p,根據步驟A中的e構造出一個雙向鏈表的節點(當前還沒有掛到雙向列表上);
C、如果雙向鏈表的尾部為空,即雙向鏈表沒有任何節點,則讓步驟B中的p既作為頭也作為尾;
如果雙向鏈表的尾部不為空:則需要將步驟B中的p掛到雙向列表的尾部;
D、最后,由於雙向列表的尾部發生了變化,需要將tl指向新的尾部節點。