ArrayList频繁扩容导致性能损耗,应预估容量初始化、批量添加前调用ensureCapacity预留空间、内存敏感时trimToSize收缩容量,并依场景选用LinkedList、CopyOnWriteArrayList等替代结构。

ArrayList 频繁扩容会触发数组复制,造成明显性能损耗。核心解决思路是:**预估容量、避免动态增长、必要时手动收缩**。
初始化时指定合理初始容量
默认构造函数创建的 ArrayList 初始容量为 10,一旦元素数量超过该值,就会触发扩容(1.5 倍增长),并复制原数组内容。若已知大致数据规模,应直接传入足够大的初始容量:
-
推荐写法:
new ArrayList(expectedSize) - 例如预计存 5000 条日志,用
new ArrayList(5000),可避免前几次扩容 - 若 size 波动大但有上限(如最多 10000),按上限设更稳妥
批量添加前调用 ensureCapacity
当已有 ArrayList 实例,又要一次性加入大量新元素(比如从数据库查出一批记录),可在 addAll 前主动预留空间:
list.ensureCapacity(list.size() + batchSize);- 这能确保后续 add 或 addAll 不触发中间扩容,尤其适合循环 add 场景
- 注意:ensureCapacity 是 public 方法,无需反射或额外依赖
扩容后考虑 trimToSize(仅当内存敏感时)
扩容会使底层数组容量远大于实际元素数(如 size=105,capacity 可能达 160)。若列表后续长期只读或不再增长,且内存占用关键(如移动端、缓存场景),可调用:
立即学习“Java免费学习笔记(深入)”;
-
list.trimToSize();—— 将 capacity 缩至当前 size - 慎用:频繁 trim 再 add 会造成反复复制,得不偿失
- 适合场景:构建完成即冻结的配置列表、一次生成多次读取的缓存集合
替代方案:根据场景选更合适的结构
如果业务中增删极为频繁且无法预估大小,ArrayList 本身可能不是最优选:
- 纯追加 + 随机读 → 仍用 ArrayList(配合预分配)
- 频繁在头部/中间插入/删除 → 考虑 LinkedList(但注意随机访问慢)
- 需高并发写 → 用 CopyOnWriteArrayList(适用于读多写少)
- 超大数据流 → 分块处理或用 Stream.iterate / Spliterator 避免全量加载



















