arraylist扩容在添加元素时触发,核心判断是size+新增元素数>elementdata.length;每次add或addall前调用ensurecapacityinternal检查容量,不足则通过grow()按1.5倍扩容并arrays.copyof拷贝。

ArrayList扩容在添加元素时触发,核心判断是 size + 新增元素数 > elementData.length。优化初始容量的关键不是猜准数字,而是避免低估——用预估上限直接初始化,能跳过多次数组拷贝。
扩容是怎么被触发的
每次调用 add(E) 或 addAll(Collection) 时,都会检查是否还能放下新元素:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
add(E e)触发单元素检查:执行ensureCapacityInternal(size + 1),只要当前已存size个元素,再加 1 就超了底层数组长度,立刻扩容 -
addAll(c)是批量检查:先算出要加的总数numNew,再调用ensureCapacityInternal(size + numNew),一次性确保够用 - 手动调用
ensureCapacity(minCapacity)也能主动触发,适合在批量操作前“提前铺路”
初始容量怎么设才合理
默认无参构造(new ArrayList())实际是懒加载:底层数组初始为 EMPTY_ELEMENTDATA,第一次 add 才真正分配长度为 10 的数组。后续扩容按 1.5 倍增长(如 10 → 15 → 22 → 33 → 49…),但每次都要 Arrays.copyOf,开销不小。
- 静态已知数量:比如读取固定配置表共 128 条,直接写
new ArrayList(128) - 分页场景:每页最多 1000 条,最多处理 3 页,就设
new ArrayList(3000) - 波动范围明确:日志聚合通常 8k–12k 条,保守设
new ArrayList(15000) - 完全不确定时,可在首次批量添加前调一次
ensureCapacity(expected),比边加边扩更轻量
哪些做法反而会拖慢性能
看似省事的操作,可能埋下性能隐患:
- 过度预留:设初始容量 100 万,结果只存几百个对象,浪费堆内存,还可能加剧 GC 压力
- 循环里反复调
ensureCapacity:比如在for (int i = 0; i 中每次调用,徒增方法调用开销 - 混淆 size 和 capacity:误以为
list.size()能反映容量,其实它只是元素个数;ArrayList 没有capacity()方法,容量靠构造参数或反射查看 - 忽略对象大小:存的是大 POJO(比如含 10KB JSON 的对象),即使容量相同,内存占用和 GC 行为也会显著不同
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










