arraylist扩容通过创建新数组复制数据实现,触发条件是size+1>elementdata.length;新容量默认为原容量1.5倍,不足则取最小需求容量,超限则安全截断;初始容量因构造方式而异,影响首次扩容行为。

Java ArrayList 底层数组通过“按需复制+容量重分配”实现动态扩容,不是真正修改原数组长度,而是创建新数组、复制旧数据、更新引用。
扩容触发时机:size + 1 > elementData.length
每次调用 add(E e) 或 add(int index, E element) 时,ArrayList 先检查是否还能容纳新元素:
- 判断依据是:当前元素个数 size 加 1 是否超过底层数组长度(elementData.length)
- 若成立(即
size + 1 > elementData.length),立即进入扩容流程 - 注意:size 是实际元素数量,elementData.length 才是当前容量;两者相等就代表已满
新容量怎么算:默认 1.5 倍,但会兜底保障
扩容核心在 grow(int minCapacity) 方法中,计算逻辑如下:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 先取旧容量:
oldCapacity = elementData.length - 默认新容量:
newCapacity = oldCapacity + (oldCapacity >> 1)(位运算等价于 ×1.5) - 但如果这个值仍小于“必须满足的最小容量”(比如批量添加 25 个元素,minCapacity=25),就直接取
minCapacity - 若新容量超过
Integer.MAX_VALUE - 8(JVM 数组长度上限),则调用hugeCapacity()做安全截断
扩容具体操作:Arrays.copyOf 创建新数组
确定好 newCapacity 后,执行三步原子动作:
- 调用
Arrays.copyOf(elementData, newCapacity)—— 底层是 native 方法,高效复制并生成新数组 - 将新数组地址赋给
elementData字段(原数组失去引用,等待 GC) - 后续所有读写操作自动落在新数组上,对上层完全透明
初始容量的特殊处理:懒加载与区分空数组
不同构造方式影响首次扩容行为:
-
new ArrayList():elementData指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA(空数组),第一次add时直接扩容到 10 -
new ArrayList(0):指向EMPTY_ELEMENTDATA,首次添加多少元素就扩多少(如 add 5 次,首次 grow 就设为 5) -
new ArrayList(12):初始elementData.length == 12,后续按 1.5 倍规则增长(12→18→27→40…)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










