无参构造函数导致首次add才分配10容量,后续按1.5倍扩容,存10万数据约触发17次复制;有参构造可预设容量避免频繁扩容,提升性能。

直接用有参构造函数指定初始容量,是最简单也最有效的扩容优化方式——它能完全避免早期频繁扩容,把复制数组的开销从运行时提前到初始化阶段。
为什么无参构造容易引发性能问题
Java 8+ 中,new ArrayList() 创建的是一个空数组(DEFAULTCAPACITY_EMPTY_ELEMENTDATA),首次 add() 才真正分配 10 个元素的空间。之后每满即扩,按 1.5 倍增长(10→15→22→33→49…)。如果最终要存 10 万条数据,这个过程会触发约 17 次扩容,每次都要复制全部已有元素。
有参构造如何精准控制初始容量
使用 new ArrayList(initialCapacity) 可跳过默认的“试探性分配”,一步到位预设空间:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 传入正整数(如
1000):直接创建长度为 1000 的Object[],后续添加不扩容,直到第 1001 个元素 - 传入 0:分配空数组
EMPTY_ELEMENTDATA,行为接近无参构造,但明确表达了“零预期”意图 - 传入负数:抛出
IllegalArgumentException,不会静默失败
怎么定这个 initialCapacity 才合理
关键不是“必须完全精确”,而是“不低于实际需要”:
- 如果知道确切数量(比如读取固定 5000 行日志),就设为 5000
- 如果只有大致范围(比如接口返回 800–1200 条记录),建议按上限设为 1200,留一点余量比反复扩容更划算
- 若完全无法预估,仍可用无参构造,但应配合
ensureCapacity()在批量操作前主动扩容
搭配 addAll 进一步减少扩容风险
即使初始容量设得略小,也优先用 addAll(collection) 一次性插入多个元素,而不是循环调用 add()。因为 addAll 内部只做一次容量检查和一次数组复制,而循环 add 可能在中途多次触发扩容。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










