当前位置: 首页 > news >正文

ArrayList 扩容机制详解

ArrayList 扩容机制详解

ArrayList 是 Java 用得最多的 List,底层是动态数组。理解扩容机制能避免一些性能问题。

1. 底层结构

transientObject[]elementData;privateintsize;

// 默认初始容量
private static final int DEFAULT_CAPACITY = 10;

注意:new ArrayList() 的时候,elementData 是一个空数组,不是长度 10 的数组。第一次 add 的时候才扩容到 10。 ```java private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }

2. add 操作

publicbooleanadd(Ee){ensureCapacityInternal(size+1);elementData[size++]=e;returntrue;}privatevoidensureCapacityInternal(intminCapacity){ensureExplicitCapacity(calculateCapacity(elementData,minCapacity));}privatestaticintcalculateCapacity(Object[]elementData,intminCapacity){if(elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA)returnMath.max(DEFAULT_CAPACITY,minCapacity);// 第一次扩到 max(10, 1)returnminCapacity;}privatevoidensureExplicitCapacity(intminCapacity){modCount++;if(minCapacity-elementData.length>0)grow(minCapacity);// 需要扩容}

3. grow 扩容

privatevoidgrow(intminCapacity){intoldCapacity=elementData.length;intnewCapacity=oldCapacity+(oldCapacity>>1);// 1.5 倍if(newCapacity<minCapacity)newCapacity=minCapacity;if(newCapacity>MAX_ARRAY_SIZE)newCapacity=hugeCapacity(minCapacity);elementData=Arrays.copyOf(elementData,newCapacity);}

扩容为原来的 1.5 倍(oldCapacity + oldCapacity / 2)。

Arrays.copyOf底层调用 System.arraycopy,是 native 方法,内存拷贝效率很高。

4. 指定初始容量

如果知道大概要放多少元素,指定初始容量可以避免多次扩容:

// 知道要放 1000 个元素List<String>list=newArrayList<>(1000);

不指定的话:10 → 15 → 22 → 33 → 49 → 73 → 109 → 163 → 244 → 366 → 549 → 823 → 1234。中间扩容了 12 次!

每次扩容都要数组拷贝,频繁扩容会影响性能。特别是数据量大的时候,一次扩容拷贝几万个元素,耗时不少。

5. 批量添加

// addAll 效率更高List<String>list=newArrayList<>(existingList.size());list.addAll(existingList);// 比 for 循环 add 好,因为内部做了容量预检查

6. trimToSize

list.trimToSize();// 缩小到实际 size

大量删除后数组还有冗余空间,可以用 trimToSize 回收内存。

7. 数组和链表的选择

ArrayList 随机访问 O(1),中间插入删除 O(n)。
LinkedList 随机访问 O(n),头尾操作 O(1)。

绝大多数场景 ArrayList 性能更好,因为:CPU 缓存对连续内存布局友好,随机访问效率远高于链表的指针跳转。除非大量头尾操作,否则优先用 ArrayList。

http://www.jsqmd.com/news/870757/

相关文章:

  • 注意力机制的幕后:它到底转化了什么?输入、输出与词向量的类比
  • 2026年5月最新邢台平乡黄金回收白银回收铂金回收权威排行榜TOP5:纯金+金条+银条+钯金 门店地址联系方式推荐 - 金诚回收
  • 终极指南:如何用puppeteer-extra-stealth插件突破网站反爬虫检测
  • 2026年5月最新邢台桥东黄金回收白银回收铂金回收权威排行榜TOP5:纯金+金条+银条+钯金 门店地址联系方式推荐 - 金诚回收
  • 当目标小到只有几个像素:深入浅出图解NWD(归一化Wasserstein距离)为何比IOU更靠谱
  • Win11Debloat:5分钟让你的Windows 11系统清理提速的终极指南
  • WinCC VBS脚本变量替换避坑指南:为什么你的‘交叉索引’里找不到某些变量?
  • 2026 西安名表回收推荐,五大平台实测对比,高价变现全攻略 - 李宏哲1
  • 2026年5月最新锡林郭勒盟太仆寺旗黄金回收白银回收铂金回收权威排行榜TOP5:纯金+金条+银条+钯金 门店地址联系方式推荐 - 金诚回收
  • CompreFace人脸识别系统:5大实战场景下的技术选型指南
  • nomic-embed-text vs text-embedding-3-small 横评
  • xtensor-stack 开源组织全解析:背景、核心项目、使用教程
  • 2026年5月最新锡林郭勒盟西乌珠穆沁旗黄金回收白银回收铂金回收权威排行榜TOP5:纯金+金条+银条+钯金 门店地址联系方式推荐 - 金诚回收
  • 2026年5月最新邢台桥西黄金回收白银回收铂金回收权威排行榜TOP5:纯金+金条+银条+钯金 门店地址联系方式推荐 - 金诚回收
  • 如何用JPEXS Free Flash Decompiler拯救即将消失的Flash数字遗产?
  • Windows 11如何轻松安装Android应用?WSA Toolbox实用指南
  • BepInEx配置管理器终极指南:如何用F1键掌控所有游戏模组设置
  • 2026年5月最新锡林郭勒盟锡林浩特黄金回收白银回收铂金回收权威排行榜TOP5:纯金+金条+银条+钯金 门店地址联系方式推荐 - 金诚回收
  • 2026年5月最新邢台清河黄金回收白银回收铂金回收权威排行榜TOP5:纯金+金条+银条+钯金 门店地址联系方式推荐 - 金诚回收
  • ESP32音频录音终极指南:从硬件连接到高质量WAV文件生成
  • ARM64虚拟化实战指南:Proxmox-Arm64项目完整部署与性能优化终极方案
  • 初创团队如何借助Taotoken统一管理多个项目的API密钥与访问权限
  • 教师减负增效全解析,深度解读PlayAI自动生成学情报告、智能作业批改与分层教案生成一体化方案
  • 2026年5月最新新疆额敏黄金回收白银回收铂金回收权威排行榜TOP5:纯金+金条+银条+钯金 门店地址联系方式推荐 - 金诚回收
  • Antv G6入门避坑指南:从‘Hello Graph’到自定义交互,新手必看的5个关键步骤
  • 2026年5月最新邢台任县黄金回收白银回收铂金回收权威排行榜TOP5:纯金+金条+银条+钯金 门店地址联系方式推荐 - 金诚回收
  • 天津卖金亲历:跑了好几家,最后只认福正美 - 上门黄金回收
  • 解决Claude Code频繁封号与Token不足问题转向稳定聚合平台
  • Win11Debloat:Windows 11系统优化终极方案,告别臃肿重获流畅体验
  • 通过 TaoToken CLI 工具一键配置多开发环境下的模型调用密钥