ensureCapacity不是自动扩容开关,而是预分配空间操作:当当前容量小于minCapacity时,扩容至max(原容量×1.5, minCapacity),不改变size,适用于已知元素总数的批量插入场景。

ArrayList 的 ensureCapacity 不是自动扩容的开关,而是“提前划好地盘”的操作——它不等元素加进来再折腾,而是在批量插入前主动申请足够空间,把复制数组的开销一次性解决掉。
底层靠数组,扩容本质是复制
ArrayList 底层用 Object[] 存数据,默认初始容量是 10(JDK 1.8+ 是懒加载,首次 add 才分配)。每次 add 时若 size == capacity,就会触发扩容:
- 新建一个更大的数组,容量通常是原容量的 1.5 倍(比如从 10 → 15,15 → 22)
- 调用 System.arraycopy 把老数组所有元素拷过去
- 更新内部引用,丢弃旧数组
这个复制过程耗时,尤其是插入上万条数据时,可能经历多次扩容(如 10→15→22→33→49…),每次都要搬一次家。
ensureCapacity 是预分配,不是实时扩容
它只做一件事:确保底层数组长度 ≥ 指定的 minCapacity。具体行为如下:
立即学习“Java免费学习笔记(深入)”;
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 如果当前 capacity 已经 ≥ minCapacity,什么也不做
- 否则,扩容至 max(原容量 × 1.5, minCapacity),且不低于 minCapacity
- 不改变 size(实际元素个数),也不触发任何 add 行为
例如:new ArrayList().ensureCapacity(100) 会让底层数组直接变成长度至少为 100 的新数组,后续 100 次 add 都不会触发扩容。
适合哪些场景?关键看“可预知”
它的价值在批量、确定数量的操作中才明显:
- 读取固定行数的文件后逐行 add 到列表
- 数据库查询返回明确条数的结果集(如 select * from t limit 5000)
- 解析 JSON 数组,已知 size 字段值
如果元素数量不确定、或只有几十个,调用它几乎没收益,反而多一次判断开销。
和构造时指定初始容量有啥区别?
两者目标一致,但时机不同:
- new ArrayList(100):构造时就分配长度为 100 的数组
- list.ensureCapacity(100):运行时任意时刻调用,对已存在的 list 生效
后者更灵活,比如 list 是方法参数传入的,你无法控制构造过程,但知道它马上要装 1000 个元素——这时 ensureCapacity 就是唯一选择。

















