HashMap原理底层剖析

resize 函数

  // 将集合扩容

           final Node[] resize() {

                   Node[] oldTab = table;

                   // 旧表的容量

                   int oldCap = (oldTab == null) ? 0 : oldTab.length;

                   // 之前的阈值

                   int oldThr = threshold;

                   int newCap, newThr = 0;

                   // 这里也可以说集合不为空

                   if (oldCap > 0) {

                       if (oldCap >= MAXIMUM_CAPACITY) {// 如果集合现在数组的长度大于等于最大容量

                           threshold = Integer.MAX_VALUE;// 将整型最大的值赋值给 threshold

                           return oldTab;

                       }

                       // 当前集合数组长度扩大二倍赋值给 newCap 小于 MAXIMUM_CAPACITY

                       // 并且集合的容量大于等于默认容量将当前阈值扩大二倍赋值给新的阈值

                       else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&

                                oldCap >= DEFAULT_INITIAL_CAPACITY)

                           newThr = oldThr << 1; // double threshold

                   }

                   // 若没有经历过初始化,通过构造函数指定了 initialCapcity ,将当前容量设置为大于它最小的 2 n 次方

                   else if (oldThr > 0)

                       newCap = oldThr;

                   else {               // 初始的时候长度和阈值都使用默认值

                       newCap = DEFAULT_INITIAL_CAPACITY;

                       newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);

                   }

                   // 重新计算 threshold

                   if (newThr == 0) {

                       float ft = (float)newCap * loadFactor;

                       newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?

                                 (int)ft : Integer.MAX_VALUE);

                   }

                   // 更新当前集合阈值

                   threshold = newThr;

                   // 从这里开始便是将 oldTab 数据重新 hash 放入扩容后的 newTab

                   @SuppressWarnings({"rawtypes","unchecked"})

                       Node[] newTab = (Node[])new Node[newCap];

                   // table 指向的 oldTab 指向 newTab

                   table = newTab;

                   if (oldTab != null) {

                       // 遍历哈希表

                       for (int j = 0; j < oldCap; ++j) {

                           Node e;

                           // 当前链表是否为 null 、并且将就链表赋值给 e

                           if ((e = oldTab[j]) != null) {

                               oldTab[j] = null;//外汇跟单gendan5.com 将原来位置的链表置为 null 方便垃圾回收

                               if (e.next == null)// 链表的长度为 1 直接将链表中的一个节点重新 hash 存放到相应的位置

                                   newTab[e.hash & (newCap - 1)] = e;

                               else if (e instanceof TreeNode) // 表示节点类型为树形结构

                                   ((TreeNode)e).split(this, newTab, j, oldCap);

                               else { // 链表是非树形结构,并且节点数量是大于 1

                                   // 将链表拆分为两个子链表

                                   Node loHead = null, loTail = null;

                                   Node hiHead = null, hiTail = null;

                                   Node next;

                                   do {  // 通过 do...while 遍历链表

                                       next = e.next;

                                       if ((e.hash & oldCap) == 0) {

                                           if (loTail == null) // 设置头节点

                                               loHead = e;

                                           else            // 设置尾结点

                                               loTail.next = e;

                                           loTail = e;// 将尾结点变为最后一个节点

                                       }

                                       else {

                                           if (hiTail == null)// 同上都是设置头节点下面也一样是设置尾结点

                                               hiHead = e;

                                           else

                                               hiTail.next = e;

                                           hiTail = e;

                                       }

                                   } while ((e = next) != null);

                                   if (loTail != null) {// 在新表的 j 位置存放链表

                                       loTail.next = null;

                                       newTab[j] = loHead;

                                   }

                                   if (hiTail != null) {// 在新表的 j+oldCap 位置存放链表

                                       hiTail.next = null;

                                       newTab[j + oldCap] = hiHead;

                                   }

                               }

                           }

                       }

                   }

                   return newTab;

               }


请使用浏览器的分享功能分享到微信等