Java 您所在的位置:网站首页 hashmap扩容时如何保证可操作 Java

Java

2023-05-25 13:07| 来源: 网络整理| 查看: 265

ArrayList 中维护了一个 Object 类型的数组 elementData

transient Object[] elementData; // transient:短暂的,表示该属性不会被序列化 每次 add 添加都要确定是否要扩容,然后再执行赋值

当创建 ArrayList 对象时,如果使用的是无参构造器 ( ArrayList() ),则初始 elementData 容量为 0 ( 实则空数组 ),第一次添加,则扩容 elementData 为 10,如果需要再次扩容,则扩容 elementData 为 1.5 倍 ( 即:0 — 10 — 15 — 22 )

第一次 add ( 因为 int 类型,还会判断是否超出 int 大小,进行装箱操作 )

add 方法里每次都要来确认 ( ensureCapacityInternal ),第一次扩容是 ensureCapacityInternal:ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));

calculateCapacity() 里 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 确认 elementData 是否为空 ( 第一次为空 ),空的话就 Math.max 扩为 10 ( 默认 DEFAULT_CAPACITY = 10 ),返回

然后 ensureExplicitCapacity() 确定扩容 ( modCount 记录修改次数,防止多线程异常 ),在此方法里判断是否容量过大溢出,如果不够,这里 grow() 真正扩容,足够的话就不需要扩容了

grow 里 1.5倍:new = old + ( old >> 1 ),if 修正使得第一次扩为 10 ( 否则 0 倍数还是 0 ),扩容机制确定后 Arrays.copyOf() 保留原数据赋给新扩容的 ( 新扩的就是 null 补上 )

最后一步步返回给 add(),list.size = 1

后面重复以上步骤:不过后面不需再 calculateCapacity() 里判空,直接返回 size + 1 给

但 Idea Debug 的时候,默认显示的数据是简化后的,如:逐条增加时可能会把新扩的 null 给加以隐藏不显示

若是想不加以简化隐藏的话就要加以设置 ( 将下图两处取消勾选 )

image-20230507104133811

如果使用的是指定大小的构造器 ( ArrayList(int) ),则初始 elementData 容量为指定大小,如果需要扩容,则直接扩容 elementData 为其现有的 1.5 倍,依此类推

源码似无参,只多了一步 this.elementData = new Object[initialCapacity]; 直接把指定的大小赋给 initialCapacity 扩容时同样 minCapacity - elementData.length > 0 进行判断,然后 grow(),直接 1.5 倍扩容,不需要修正


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有