ArrayList扩容机制

一、ArrayList 基础认知

ArrayList 是非线程安全 的动态数组,底层实现为Object[]数组,它的核心优势是支持随机访问、查询效率极高,同时封装了自动化的容量管理逻辑,屏蔽了数组固定长度的弊端。

重点:JDK 7 及之后,ArrayList 采用懒加载机制,初始化时不会直接分配容量,只有真正添加元素时,才会触发容量分配。

二、什么是自动扩容?

我们先明确核心定义:自动扩容是 ArrayList 的核心能力:

  1. 初始化时创建空数组,不占用实际内存空间;
  2. 执行元素添加操作时,正式分配内存容量;
  3. 当添加元素导致现有容量不足时,底层会自动创建一个更大的新数组,将原数组元素复制到新数组中,完成扩容。

简单来说:数组长度固定不可变,ArrayList 通过「创建新数组 + 复制元素」模拟了动态扩容效果

三、ArrayList 扩容全流程(核心源码逻辑)

我们以 JDK 8 为基准,拆解扩容的每一步执行逻辑,这也是面试高频考点。

1. 扩容触发时机

执行add()/addAll()方法添加元素时,会触发容量检查 :判断条件:当前元素个数 + 1 > 数组现有容量

  • 条件不成立:直接添加元素
  • 条件成立:立即触发扩容流程

2. 核心扩容步骤

(1)懒加载初始化

无参构造创建 ArrayList:new ArrayList()底层数组:private transient Object[] elementData = {};(空数组)第一次添加元素 时,直接将容量扩容为默认值 10

(2)计算新容量

ArrayList 默认扩容规则:新容量 = 旧容量 + 旧容量 >> 1扩容为原容量的 1.5 倍 >> 1是右移一位,等价于除以 2,运算效率远高于除法。

(3)严格的容量校验

扩容不是无限的,JDK 做了双层安全校验:

  1. 如果 1.5 倍后的新容量 < 最小需要容量(如批量添加大量元素),直接以「最小需要容量」作为新容量;
  2. 如果新容量超过MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8,则直接使用Integer.MAX_VALUE(2^31-1)作为最终容量。

关键疑问解答:① 为什么是Integer.MAX_VALUE - 8?部分虚拟机需要在数组对象头中存储数组长度信息,预留 8 字节空间,避免内存溢出(OOM),这是推荐安全上限 。② 为什么最终可以用Integer.MAX_VALUE-8是安全建议,不是物理上限,当容量不足时,JDK 会用 int 类型的最大值做兜底保障

(4)数组复制完成扩容

底层通过Arrays.copyOf()方法实现:

  1. 创建新容量的数组;
  2. 将原数组元素浅拷贝到新数组;
  3. elementData指向新数组,丢弃旧数组。

性能瓶颈:数组拷贝是耗时操作,频繁扩容会大幅降低 ArrayList 性能。

四、完整扩容流程总结

  1. 初始化:空数组,无容量分配;
  2. 首次添加:容量直接变为 10;
  3. 常规添加:检查容量,不足则扩容 1.5 倍;
  4. 容量校准:优先满足最小需求,再限制最大容量;
  5. 数组复制:完成扩容,替换底层数组。

五、ArrayList 扩容实战优化(开发必备)

扩容的核心损耗是数组复制 ,想要提升性能,核心思路:减少扩容次数

优化方案 1:指定初始容量(最常用)

如果提前知道元素数量,创建 ArrayList 时直接指定容量,从根源避免扩容:

复制代码
// 坏代码:未知会触发多次扩容
List<String> list = new ArrayList<>();
// 好代码:提前指定1000容量,零扩容
List<String> list = new ArrayList<>(1000);

优化方案 2:批量添加时手动扩容

添加大量元素前,手动调用ensureCapacity(int minCapacity)方法,一次性扩容到位:

复制代码
List<String> list = new ArrayList<>();
// 手动扩容,提前分配足够容量
list.ensureCapacity(1000);
// 批量添加元素,无额外扩容
for (int i = 0; i < 1000; i++) {
    list.add("测试");
}

优化方案 3:避免中间插入 / 删除

数组结构决定了中间操作会触发元素移动,结合扩容会进一步降低性能,高频增删场景建议使用 LinkedList。

相关推荐
M ? A13 分钟前
解决 VuReact 中 ESLint 规则冲突的完整指南
前端·react.js·前端框架
摇滚侠23 分钟前
搭建前端开发环境 安装 nodejs 设置淘宝镜像 最简化最标准版本 不使用 NVM NVM 高版本无法安装低版本 nodejs
java·开发语言·node.js
花千树-01029 分钟前
兼容 ThreadLocal 的用户上下文透传方案:WebFlux 项目改造实践
java·spring boot·servlet·jetty
Jave21081 小时前
实现全局自定义loading指令
前端·vue.js
奔跑的呱呱牛1 小时前
CSS Grid 布局参数详解(超细化版)+ 中文注释 Demo
前端·css·grid
木斯佳1 小时前
前端八股文面经大全:影刀AI前端一面(2026-04-01)·面经深度解析
前端·人工智能·沙箱·tool·ai面经
重生之我是Java开发战士1 小时前
【动态规划】简单多状态dp问题:按摩师,打家劫舍,删除并获得点数,粉刷房子,买卖股票的最佳时机
算法·动态规划·哈希算法
小江的记录本2 小时前
【Linux】《Linux常用命令汇总表》
linux·运维·服务器·前端·windows·后端·macos
KAU的云实验台2 小时前
单/多UAV、静/动态路径规划,基于PlatEMO平台的带约束多目标优化 本文核心内容:
算法·matlab·无人机
Liangwei Lin2 小时前
洛谷 P1807 最长路
数据结构·算法