zoukankan      html  css  js  c++  java
  • HashMap之扩容resize(四)

    之前讲HashMap之Put方法操作有提到过扩容操作,扩容简单理解就是原容器不够大了,需要提供一个更大的容器。而JAVA里数组的扩容也没有更高级的办法,就是创建一个新的数组,然后将旧数组的数据拷贝过来。

    看一下扩容的详细流程:

    流程讲解:

    1)计算新数组Table的newCap(容量),newThr(阀值)。

    2)new一个新数组,Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];

    3)遍历旧数组,将数据拷贝到新数组

    4)依次判断旧数组每一个节点(也就是桶)对象类型,分为单节点,链表,红黑树三种情况。类型不同,拷贝的方式不同。

    JDK1.7和JDK1.8扩容最大的不同是:JDK1.7扩容时需要重新计算key的hash值(rehash),然后分配到新的数组Table里。而JDK1.8每次扩容都是以2的幂数增长,节点的索引值要么和原来一样,要么就是原索引+oldCap,避免了重新rehash消耗性能。

        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);
        
        if (loTail != null) {
            loTail.next = null;
            newTab[j] = loHead;
        }
        if (hiTail != null) {
            hiTail.next = null;
            newTab[j + oldCap] = hiHead;
        }

    从上面的源码可以看到,JDK1.8中只需要看看原来的hash值新增的那个bit是1还是0就好了,是0的话索引没变,是1的话索引变成“原索引+oldCap”。

  • 相关阅读:
    HTML5新增
    【目录】洛谷|CODEVS题解汇总
    【搜索】kkksc03考前临时抱佛脚
    【模拟】压缩技术
    【模拟】爱与愁的一千个伤心的理由
    【搜索】棋盘
    【模拟】图书管理员
    【递归】对称二叉树
    【题单】挖坑大行动
    【模拟】弹珠游戏
  • 原文地址:https://www.cnblogs.com/shileibrave/p/9847764.html
Copyright © 2011-2022 走看看