能,但只对新增有效且需在大量add前调用;它不减少remove开销、不回收空间,仅避免add触发的多次扩容拷贝。

ensureCapacity() 真的能减少重分配吗?
能,但只对「新增」有效,且必须在大量 add() 操作前调用;它对 remove() 完全无影响,也不会回收已分配空间。ArrayList 内部数组扩容只发生在 add() 触发容量不足时,而 ensureCapacity() 的作用就是提前把底层数组(elementData)扩到指定大小,避免后续多次 resize —— 每次 resize 都涉及新数组分配 + 元素拷贝,是 O(n) 开销。
常见误判:以为调用一次 ensureCapacity(100) 后再删掉 90 个元素,内存就会自动缩容 —— 不会。ArrayList 从不自动缩小数组,trimToSize() 才干这事,而且它也不属于“减少重分配”,而是释放冗余内存。
什么时候调用 ensureCapacity() 才真正省开销?
典型场景是「可预估最终规模的批量构建」,比如从数据库查出 5000 条记录逐个 add,或解析一个已知长度的 JSON 数组。此时在循环前调用 ensureCapacity() 可避免多次扩容(默认初始容量 10,扩容策略是 1.5 倍,5000 个元素至少触发约 12 次数组拷贝)。
- ✅ 推荐:已知最终 size(如
list.size() == expectedSize成立前),且主要操作是add() - ❌ 无效:边 add 边 remove、或插入位置随机(
add(int index, E)可能触发数组移动,但不触发扩容逻辑) - ⚠️ 注意:
ensureCapacity()参数是「最小需要容量」,不是「精确容量」;传 100 不代表数组长度变成 100,只是确保 ≥100;若当前已 ≥100,则无操作
和构造函数 initialCapacity 比,有啥区别?
本质一样,都是设初始数组大小,但时机不同:new ArrayList(100) 在实例化时就分配好数组;ensureCapacity(100) 是对已有实例“事后扩容”。实际性能差异极小,但语义更清晰:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 构造时就知道规模 → 用
new ArrayList(initialCapacity) - 实例已存在、稍后才确定要塞多少数据 → 用
ensureCapacity() - 二者都只影响扩容起点,不影响
size()(即逻辑元素个数),调用后size()仍是 0
示例:
ArrayList<string> list = new ArrayList(); list.ensureCapacity(5000); // 底层数组现在至少长 5000 for (int i = 0; i <h3>容易被忽略的坑:ensureCapacity() 不解决并发和结构性修改问题</h3> <p>即使你精准调用了 <code>ensureCapacity()</code>,以下情况仍会触发意外开销或异常:</p> <ul> <li>多线程同时 <code>add()</code> → 即使容量足够,也可能因竞争导致重复扩容(ArrayList 非线程安全)</li> <li>用 <code>list.iterator().remove()</code> 或 <code>removeIf()</code> 删除大量元素 → 数组不变,但后续 <code>add()</code> 仍按当前 <code>size()</code> 判断是否扩容,可能造成严重空间浪费</li> <li>调用 <code>clear()</code> 后继续 add → 底层数组没变,但 <code>size</code> 归零;如果之后只加几十个元素,那之前预分配的 5000 就纯属闲置内存</li> </ul> <p>所以,预分配只是优化手段之一,不能替代对使用模式的判断。真正高频增删的场景,该换 <code>LinkedList</code>(插入删除快)、或上 <code>ArrayDeque</code>(作为栈/队列更高效)、甚至考虑对象池 —— 而不是死磕 <code>ensureCapacity()</code>。</p></string>
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










