hashmap和concurrenthashmap源码分析(1.7/1.8)

final Node[] resize() {

     Node[] oldTab = table;

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

     int oldThr = threshold;

     int newCap, newThr = 0;

     if (oldCap > 0) {

        // 1 判断老表的容量是否超过最大容量值:如果超过则将阈值设置为 Integer.MAX_VALUE ,并直接返回

      // 此时 oldCap * 2 Integer.MAX_VALUE 大,因此无法进行重新分布,只是单纯的将阈值扩容到最大

         if (oldCap >= MAXIMUM_CAPACITY) {

             threshold = Integer.MAX_VALUE;

             return oldTab;

         }

       // newCap 赋值为 oldCap 2 倍,如果 newCap< 最大容量并且 oldCap>=16, 则将新阈值设置为原来的两倍

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

             newThr = oldThr << 1; // double threshold 24

     }

     //2. 如果老表的容量为 0, 老表的阈值大于 0, 是因为初始容量被放入阈值,则将新表的容量设置为老表的阈值

     else if (oldThr > 0)

         newCap = oldThr;

     else {

         //3. 老表的容量为 0, 老表的阈值为 0 ,这种情况是没有传初始容量的 new 方法创建的空表,将阈值和容量设置为默认值。

         newCap = DEFAULT_INITIAL_CAPACITY;

         newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);

     }

     // 4. 如果新表的阈值为空 , 则通过新的容量 * 负载因子获得阈值

     if (newThr == 0) {

         float ft = (float)newCap * loadFactor;

         newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE);

     }

   // 将当前阈值设置为刚计算出来的新的阈值,定义新表,容量为刚计算出来的新容量,将 table 设置为新定义的表。

     threshold = newThr;

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

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

     table = newTab;

   // 6. 如果老表不为空,则需遍历所有节点,将节点赋值给新表

     if (oldTab != null) {

         // 把每个 bucket 都移动到新的 buckets

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

             Node e;

             if ((e = oldTab[j]) != null) {   // 将索引值为 j 的老表头节点赋值给 e

                 oldTab[j] = null;         // 将老表的节点设置为空 , 以便垃圾收集器回收空间

   //7. 如果 e.next 为空 , 则代表老表的该位置只有 1 个节点,外汇跟单gendan5.com计算新表的索引位置 , 直接将该节点放在该位置

                 if (e.next == null)

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

    //8. 如果是红黑树节点,则进行红黑树的重 hash 分布 ( 跟链表的 hash 分布基本相同 )

                 else if (e instanceof TreeNode)

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

                 else {

     // 9. 如果是普通的链表节点,则进行普通的重 hash 分布

                     Node loHead = null, loTail = null;// 存储索引位置为 : “原索引位置”的节点

                     Node hiHead = null, hiTail = null;// 存储索引位置为 : “原索引位置 +oldCap ”的节点

                     Node next;

                     do {

                         next = e.next;

           // 如果 e hash 值与老表的容量进行与运算为 0, 则扩容后的索引位置跟老表的索引位置一样

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

                             if (loTail == null)  // 如果 loTail 为空 , 代表该节点为第一个节点                             

                                 loHead = e;     // 则将 loHead 赋值为第一个节点

                             else

                                 loTail.next = e; // 否则将节点添加在 loTail 后面                            

                             loTail = e;   // 并将 loTail 赋值为新增的节点

                         }

              // 如果 e hash 值与老表的容量进行与运算为非 0, 则扩容后的索引位置为 : 老表的索引位置+ oldCap                        

                         else {

                             if (hiTail == null)  // 如果 hiTail 为空 , 代表该节点为第一个节点                              

                                 hiHead = e;    // 则将 hiHead 赋值为第一个节点

                             else

                                 hiTail.next = e;   // 否则将节点添加在 hiTail 后面

                             hiTail = e;      // 并将 hiTail 赋值为新增的节点

                         }

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

        // 10. 如果 loTail 不为空(说明老表的数据有分布到新表上“原索引位置”的节点),则将最后一个节点的 next 设为空,并将新表上索引位置为“原索引位置”的节点设置为对应的头节点                   

                     if (loTail != null) {

                         loTail.next = null;

                         newTab[j] = loHead;

                     }

                 // 11. 如果 hiTail 不为空(说明老表的数据有分布到新表上“原索引 +oldCap 位置”的节点),则将最后一个节点的 next 设为空,并将新表上索引位置为“原索引 +oldCap ”的节点设置为对应的头节点

                     if (hiTail != null) {

                         hiTail.next = null;

                         newTab[j + oldCap] = hiHead;

                     }

                 }

             }

         }

     }

        //12. 返回新表

     return newTab;

}


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