美文网首页
HashMap:如何进行扩容?

HashMap:如何进行扩容?

作者: 木头与琉璃 | 来源:发表于2019-10-22 11:26 被阅读0次

在说明hashMap如何进行扩容之前,先说下为什么要进行扩容?是因为hashMap初始化的容量不够用了吗?不是,是因为当hashMap元素的个数 > hashMap容量*0.75时,存储新元素发生hashcode碰撞的概率变得很大。那么,什么是hashcode碰撞?

1.什么是hashcode碰撞?

hashcode碰撞就是当存入多个元素的时候,元素key的hashcode出现了一样的情况。当hashmap存入元素的时候,如果碰撞较少,那么出现的存储情况如图:

碰撞较少
如果碰撞比较频繁,就会出现的存储情况如图:
碰撞比较频繁
综上:hashcode碰撞会导致hashMap中元素分布不均衡,hashMap中元素分布不均衡就会导致查找元素的效率变得很低。

2.怎么减少hashcode碰撞的几率,使元素的分布更加均匀?

hashMap为了减少hashcode碰撞的几率,会在对key进行hash的时候进行扰动,也就是让计算出来的hashCode更随机。

// > java8
 (h = key.hashCode()) ^ (h >>> 16)

但即使这样,当hashMap元素的个数 > hashMap容量*负载因子(默认0.75)时,hashcode碰撞的概率也会变得较为频繁。这时候就需要对hashmap进行扩容了。

3.hashMap怎么进行扩容?

    /**
     * 初始化table或者将table扩容未两倍
     */
    final Node<K,V>[] resize() {
        Node<K,V>[] 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;
                return oldTab;
            }
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                     oldCap >= DEFAULT_INITIAL_CAPACITY)
                newThr = oldThr << 1; // 扩容后数组的长度,扩容后的阀值 = (扩容后数组的长度,扩容后的阀值)*2
        }
       
        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);
                        if (loTail != null) {
                            loTail.next = null;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
                            hiTail.next = null;
                            newTab[j + oldCap] = hiHead;
                        }
                    }
                }
            }
        }
        return newTab;
    }

相关文章

  • HashMap:如何进行扩容?

    在说明hashMap如何进行扩容之前,先说下为什么要进行扩容?是因为hashMap初始化的容量不够用了吗?不是,是...

  • HashMap、HashSet、TreeMap、LinkedHa

    HashMap HashMap底层实现是数组+链表。数组大小不满足时要进行扩容操作,扩容是将容量扩展为原先的2倍,...

  • HashMap扩容机制

    HashMap如何扩容的 HashMap里面数据存储数量=threshold,而threshold是由tableS...

  • 2020-04-03 Java HashMap的实现原理的文章

    HashMap的扩容机制---resize() HashMap底层实现原理 扩容机制 Java中HashMap的实现原理

  • HashMap原理

    本文参考: HashMap的扩容机制---resize()HashMap的扩容及树化过程 HashMap的内部是使...

  • HashMap如何扩容?

    扩容部分我们需要重点关注,其余内容可以阅读上篇博客 扩容原理 1.扩容需要将桶的长度,更新的新长度;2.将所有对象...

  • JDK1.7 版本中 HashMap 扩容

    扩容扩容是指当容器中元素的数量达到某个阈值时,容器自己进行的容量翻倍的操作。 JDK1.7 HashMap 扩容方...

  • JAVA面试题「社招篇」

    1. hashcode跟equals 2. hashmap的实现原理 3. 如何扩容,为什么要扩容 4. 1.6 ...

  • HashMap 如何解决冲突,扩容机制

    HashMap 如何解决冲突,扩容机制 我们来看看HashMap的put数据的时候,是怎么处理的: 计算HashC...

  • HashMap初始容量和扩容

    《阿里巴巴Java开发手册》中对于HashMap有推荐用法 那么HashMap是如何扩容的呢?通过查阅源码可以看出...

网友评论

      本文标题:HashMap:如何进行扩容?

      本文链接:https://www.haomeiwen.com/subject/rxttvctx.html