HashMap1.8 resize()

HashMap1.8会在两处resize,一处是在第一次put元素时初始化table,

另一处是在table的size大于threshold时需要扩容(threshold = table.的capacity * loadFactor;)

    /**
     * Initializes or doubles table size.  If null, allocates in
     * accord with initial capacity target held in field threshold.
     * Otherwise, because we are using power-of-two expansion, the
     * elements from each bin must either stay at same index, or move
     * with a power of two offset in the new table.
     *
     * @return the table
     */
    final Node<K,V>[] resize() {

        Node<K,V>[] oldTab = table;//旧表,需要扩容的table或者还未初始化的table
        int oldCap = (oldTab == null) ? 0 : oldTab.length;//旧表的容量
        int oldThr = threshold;//旧表的扩容阈值
        int newCap, newThr = 0;//新表的容量,新表的扩容阈值
        if (oldCap > 0) {//旧表容量不为0,表示table已经初始化了

                //旧表容量已经达到最大值,则返回旧表,不再扩容

                if (oldCap >= MAXIMUM_CAPACITY) {

                        //更新当前的阈值为int的最大值,下次判断threshold已是最大值则不再扩容。
                        threshold = Integer.MAX_VALUE;
                        return oldTab;
                    }

                //旧表容量扩大一倍得到新容量,新容量未超过最大临界值且旧表容量大于等于默认初始容量,旧表的扩容阈值也同样扩大一倍得到新表的扩容阈值

                else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                     oldCap >= DEFAULT_INITIAL_CAPACITY)
                newThr = oldThr << 1; // double threshold
        }//以下两种情况为table还未初始化,oldThr > 0为调用了HashMap的有参构造函数,threshold已有值;另一种情况为调用了//HashMap的无参构造函数

        else if (oldThr > 0) // initial capacity was placed in threshold
            newCap = oldThr;//新表容量为threshold
        else {               // zero initial threshold signifies using defaults
            newCap = DEFAULT_INITIAL_CAPACITY;//新表容量为默认初始容量
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);//新表扩容阈值为默认加载因子*默认初始容量
        }

        //else if (oldThr > 0) 这个分支,newThr=0,计算新表阈值
        if (newThr == 0) {
            float ft = (float)newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }
        threshold = newThr;
        @SuppressWarnings({"rawtypes","unchecked"})
        Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
        table = newTab;
        if (oldTab != null) {//旧表数组有元素,遍历数组的每个桶
            for (int j = 0; j < oldCap; ++j) {
                Node<K,V> e;

                //旧表对应下标有元素
                if ((e = oldTab[j]) != null) {
                    oldTab[j] = null;

                    //旧表对应下标位置只有一个元素,则计算该元素在新表的位置,放入该节点
                    if (e.next == null)
                        newTab[e.hash & (newCap - 1)] = e;

           //这个元素属于树节点,该节点放入树状结构中

           else if (e instanceof TreeNode)
                        ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);

                    //对应下标的位置是一条链表

                   else { // preserve order

                        //创建旧表的头结点,尾结点;新表的头结点,尾结点
                        Node<K,V> loHead = null, loTail = null;
                        Node<K,V> hiHead = null, hiTail = null;
                        Node<K,V> next;

                     //循环遍历链表上节点,将节点放入两条链表之一,尾插法

                     do {
                            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);

                      //链表尾部元素为null,将两条链表头结点放入新表中对应下标位置

                       if (loTail != null) {
                            loTail.next = null;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
                            hiTail.next = null;

                           //新表下标位置=旧表下标索引+旧表容量oldCap

                           newTab[j + oldCap] = hiHead;
                        }
                    }
                }
            }
        }
        return newTab;
    }

扩容后索引重排,下图为旧表

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值