• 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”。

  • 相关阅读:
    JavaScript深入解读
    CentOS7上安装与配置Tomcat8与MySQL5.7
    码云的初步使用
    MySQL安装与初步操作
    自定义消息队列
    用Executors工具类创建线程池
    Java中的BlockingQueue队列
    Restful对于URL的简化
    docker push 实现过程
    通过docker-machine和etcd部署docker swarm集群
  • 原文地址:https://www.cnblogs.com/shileibrave/p/9847764.html
Copyright © 2020-2023  润新知