hashmap 源码解析 扩容

本文深入探讨HashMap的扩容机制,包括初始化扩容与动态扩容的过程。详细分析了不同构造函数下HashMap的初始化大小及扩容阈值,并解释了触发扩容的条件及扩容的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章是针对 前两篇
hashmap 实现原理总结
hashmap 源码解析 new HashMap()
的补充,主要是讲解hashmap 是怎么进行扩容的。
先大概说下总结,后面在进行详细描述

  1. 如果使用的无参的构造函数申明的hashmap 在第一次put 数据的时候回进行初始化扩容,初始化map 大小是16, 扩容阈值是 12
  2. 如果使用了带参数的构造函数申明的hashmap, 在第一次put 数据的时候也会进行初始化扩容(new的时候 并没有生成一个完整的map) 初始化 map 大小是传入参考最接近2的整数次幂的数, 扩容阈值是 map 大小 *0.75
  3. 如果不是首次扩容 且没有超过 最大限制, 直接 扩容一倍

什么时候会进行扩容

通过查看hashmap putVal() 的源码 发现有两个地方会触发扩容机制

if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;

就是table 为空,还没有插入元素的时候, 这时候进行的是初始化扩容

if (++size > threshold)
            resize();

map 里面元素的个数大于 扩容阈值(threshold) 的时候,会触发扩容机制

如何进行扩容

我们查看 resize() 函数,通过阅读源码来梳理 hashmap是如何进行扩容的

    final Node<K,V>[] resize() {
      // 如果是第一次put 数据 , tables 是 null
        Node<K,V>[] oldTab = table;
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        // 扩容阈值  
        // 1. 如果是 new hashmap() 第一次put的时候   threshold为0
        // 2. 如果是 new hashmap(n) 第一次put 的时候  threshold 为 最接近n 的2的整数次幂的数 (https://blog.youkuaiyun.com/sessionsong/article/details/98211616)
        int oldThr = threshold; 
        int newCap, newThr = 0;
        if (oldCap > 0) { // 老容器不为空,所有是第二次或者是第n 次扩容 
            if (oldCap >= MAXIMUM_CAPACITY) { // 操作最大限制 
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&  // 没有超过  扩容一倍
                     oldCap >= DEFAULT_INITIAL_CAPACITY)
                newThr = oldThr << 1; // double threshold
        }
        // 如果oldThr  >0 也就是threshold >0  也就是 new HashMap(int initialCapacity)/ HashMap(int initialCapacity, float loadFactor) 形式申明的map 对象
        else if (oldThr > 0) // initial capacity was placed in threshold
            newCap = oldThr;
        else {               // zero initial threshold signifies using defaults
        // new hashmap()形式申明的对象
            newCap = DEFAULT_INITIAL_CAPACITY;
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
        }
        if (newThr == 0) { // 重点: newThr  只有 oldCap 为空 且 oldThr为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;
       //  下面是 扩容后  元素复制逻辑  可以暂时不研究
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值