詳細解釋JDK8HashMap的擴容核心


昨天看懂了JDK7Hashmap的擴容頭插法,及其可能產生的循環引用問題,今天看看JDK8的HashMap擴容實現。采取的是用四個結點,兩條鏈表完成重新分配位置,比較簡單有趣。解析如下:

 1  //如果原來的table等於null,直接返回
 2         if (oldTab != null) {
 3             //遍歷原來的table,bucket
 4             for (int j = 0; j < oldCap; ++j) {
 5                 HashMap.Node<K, V> e;//bucket
 6                 if ((e = oldTab[j]) != null) {//如果當前桶位上有元素,不為null
 7                     oldTab[j] = null;//當前位置置空
 8                     if (e.next == null)//如果只有一個元素e,e.next為null,直接安排e到新表新家
 9                         newTab[e.hash & (newCap - 1)] = e;
10                     else if (e instanceof HashMap.TreeNode)//判斷e是不是樹形節點,也就是超過8個元素
11                         ((HashMap.TreeNode<K, V>) e).split(this, newTab, j, oldCap);//
12                     else { // preserve order
13                         HashMap.Node<K, V> loHead = null, loTail = null;//低位的頭結點,尾結點
14                         HashMap.Node<K, V> hiHead = null, hiTail = null;//高危的頭結點,尾結點
15                         HashMap.Node<K, V> next;//下個節點
16                         do {//在這個循環里,依次處理該桶上鏈表,分裂成高位鏈和低位鏈
17                             next = e.next;//后一個節點元素
18                             //如果元素的hash值,與 原來表的容量 等於0,實際上是把原來在一個桶位的元素分流
19                             //例如e.hash & 10000,值會有0和1兩種,等於0的,還是相對於原表的索引位置
20                             //等於1,把他向高位調整
21                             if ((e.hash & oldCap) == 0) {
22                                 if (loTail == null)//只有第一次進來的時候,loTail為null
23                                     loHead = e;//設置頭結點位e
24                                 else
25                                     loTail.next = e;//尾插
26                                 loTail = e;//低位鏈指針下移
27                             } else {
28                                 if (hiTail == null)
29                                     hiHead = e;
30                                 else
31                                     hiTail.next = e;
32                                 hiTail = e;
33                             }
34                         } while ((e = next) != null);
35                         //while循環完之后,大概會形成兩個鏈表【高位鏈hiHead--hiTail,低位鏈loHead--loTail】,最極端的情況是只有高位鏈或
36                         //只有低位鏈。拿着這兩個鏈表,插入到對應桶位,入駐新家。
37                         //判斷低位鏈中是否有元素
38                         if (loTail != null) {
39                             loTail.next = null;//干掉低位鏈尾部的next,因為e的下一個結點很可能被分到高位,所以我們要干掉這個叛徒
40                             newTab[j] = loHead;
41                         }
42                         //判斷高位鏈中是否有元素
43                         if (hiTail != null) {
44                             hiTail.next = null;
45                             newTab[j + oldCap] = hiHead;
46                         }
47                     }
48                 }
49             }
50         }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM