最简单有效的优化方式是创建arraylist时指定合理初始容量,需结合业务预估数据规模:如商品列表800–1200条则设1200,日志任务5万条则设50000;无法预估时可用ensurecapacity兜底,批量添加优先用addall以避免多次扩容。

直接在创建 ArrayList 时指定合理初始容量,是最简单、最有效的优化方式。关键不是“能不能设”,而是“设多少才合适”——设小了仍要扩容,设大了浪费内存,所以得结合业务场景预估。
明确预估数据规模再设容量
如果接口返回的商品列表通常在 800–1200 条之间,那就设成 1200;如果日志聚合任务每次处理约 5 万条记录,就用 new ArrayList(50000)。避免凭感觉写个 100 或 10000,而应基于监控数据或历史统计。
- 查数据库前先
SELECT COUNT(*)(适合低频、强一致性场景) - 用缓存或配置项存常见集合大小的上限值
- 对分页接口,初始容量可设为
pageSize × maxPage(如每页 20 条、最多查 5 页 → 设 100)
用 ensureCapacity 提前兜底
有些场景无法在构造时确定大小(比如流式组装、条件分支拼接),可在添加前统一调用 ensureCapacity:
-
list.ensureCapacity(expectedSize)不会缩小数组,只在不足时扩容 - 它内部按 1.5 倍增长,但如果
expectedSize超过该值,会直接按需分配,不妥协 - 比循环中反复 add 再触发多次 grow 更可控,实测可减少 80% 以上复制开销
批量添加优先用 addAll 而非循环 add
ArrayList 的 addAll 方法自带容量预判逻辑:它会先算出最终需要的总容量(size + collection.size()),再一次性 grow 到位,避免边加边扩。
- 错误写法:
for (String s : items) list.add(s);—— 每次都可能触发 grow - 推荐写法:
list.addAll(items);—— 底层自动做一次精准扩容 - 即使
items是另一个 ArrayList,addAll也能复用其size()快速估算
别为了“省一点内存”牺牲可预测性
有人担心设大了浪费堆内存,但比起频繁扩容带来的 GC 压力、CPU 复制耗时和响应抖动,这点空间成本几乎可以忽略。JVM 中一个空 Object[] 占用很小,而一次 10 万元素的数组复制可能让单次请求多耗 20ms+。
- 内存敏感服务(如嵌入式或函数计算)可适度保守,但至少设到预估均值的 1.2 倍
- 高吞吐 Web 服务建议设到预估最大值,宁可略大,不冒扩容风险
- 可通过 JVM 参数
-XX:+PrintGCDetails观察是否因 ArrayList 临时数组引发 Minor GC 高频
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











