如何使用 ArrayList 的 ensureCapacity 优化大数据的扩容

酷敏吖_8160

酷敏吖_8160

2026-04-14

874人浏览

原创

ensureCapacity在大数据插入前调用可避免多次数组复制,但需准确预估总量;它适用于构造后才获知规模的场景,参数应直接传最终预期元素总数,而非当前size加增量。

如何使用 arraylist 的 ensurecapacity 优化大数据的扩容

直接说结论:ensureCapacity 在大数据插入前调用,能避免多次数组复制,但必须配合合理预估——它不解决“估算不准”的问题,只放大你预估的准确性。

什么时候该用 ensureCapacity 而不是 new ArrayList(int)

两者都设初始容量,但行为不同:

  • new ArrayList(1000):构造时就分配长度为 1000 的数组,elementData.length == 1000,后续 add 不触发第一次扩容
  • new ArrayList() + ensureCapacity(1000):构造时用的是共享空数组 DEFAULTCAPACITY_EMPTY_ELEMENTDATA,调用 ensureCapacity 后才真正分配长度 1000 的数组(跳过默认首次扩到 10 的中间步骤)
  • 关键区别:如果你在构造后、add 前才拿到数据规模(比如从 DB 查询 count 或流式读取 header),ensureCapacity 是唯一能“补救”的时机;而构造函数要求容量已知

ensureCapacity(minCapacity) 的 minCapacity 怎么算才不翻车

常见错误是传 list.size() + N,但这是错的——ensureCapacity 看的是底层数组长度(elementData.length),不是当前元素个数(size)。它要确保“至少能容纳 minCapacity 个元素”,所以应直接传最终预期总数量:

  • 要插入 5000 条数据?传 5000,不是 list.size() + 5000(除非 list 已有内容)
  • 循环中分批 add?别在每次循环里调 ensureCapacity,只在最开始调一次,传总目标量
  • 如果数据量动态变化(如流式解析 JSON 数组),宁可略高估(+10%),也不要低估——低估一次就白干,触发扩容仍要复制

为什么 ensureCapacity 有时没效果?三个典型陷阱

现象:调了 list.ensureCapacity(10000),但跑起来还是看到多次 grow() 日志或 GC 尖峰。原因往往在这:

人工智能数字技术机器人全息大脑大数据分析矢量素材(EPS)
人工智能数字技术机器人全息大脑大数据分析矢量素材(EPS)

这是一款人工智能数字技术机器人全息大脑大数据分析矢量素材,格式为 EPS,含 JPG 预览图。

下载
  • 调用太晚:在第一次 add() 之后才调——此时 ensureCapacityInternal 已被触发,内部数组已扩到 10,再调 ensureCapacity 只能基于 10 做 1.5 倍增长(10→15→22→33…),无法一步到位
  • 传参小于当前 elementData.length:比如 list 已有 8000 元素且容量是 12000,再传 10000 就完全无效(minCapacity 时方法直接返回)
  • 和 trimToSize() 冲突:如果之前调过 trimToSize() 把容量压到 size,再调 ensureCapacity 才有效;否则可能被“压扁”后又反复扩

大数据场景下,ensureCapacity 和 grow 的实际开销在哪

重点不是 ensureCapacity 本身耗时(它只是比较+分支),而是它背后触发的 grow() ——这才是性能瓶颈所在:

  • grow() 必然执行 Arrays.copyOf(elementData, newCapacity),本质是 System.arraycopy,时间复杂度 O(n),n 是当前元素个数
  • 新容量计算:JDK 8+ 是 oldCapacity + (oldCapacity >> 1)(即 ×1.5),不是四舍五入,比如 10→15、15→22、22→33……所以预设 10000 比预设 9999 更省一次扩容
  • 内存压力:一次复制 100 万字符串引用,会瞬间申请一块大内存,容易触发 Young GC;若预估过大(比如传 1000 万但只存 10 万),浪费堆空间,还可能引发 Full GC

最易被忽略的一点:ensureCapacity 不改变 size,也不初始化元素——它只管底层数组长度。如果你依赖 get(i) 随机访问未 add 过的位置,依然会抛 IndexOutOfBoundsException,这点和数组声明 new String[1000] 不同。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

大数据

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

11477

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

8602

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

7392

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1224

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

988

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1476

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

3009

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20271

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1315

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 193人学习

大数据(MySQL)视频教程完整版
大数据(MySQL)视频教程完整版

共200课时 | 28.7万人学习

PHP会话控制/文件上传/分页技术
PHP会话控制/文件上传/分页技术

共22课时 | 2.9万人学习