ArrayList扩容机制

简介: 本文深入解析ArrayList扩容机制:首次添加元素时默认容量为10,后续每次扩容为原容量的1.5倍,通过grow()方法实现动态扩容,并结合源码分析add、ensureCapacityInternal等关键方法的执行流程。

6⌥codecode6⌥codecodeArrayList扩容机制

免费使用


ArrayList扩容机制

先来看Add方法

Java

运行代码复制代码

1

2

3

4

5

6

7

8

9

10

/**

*将指定的元素追加到此列表的末尾

*/

public boolean add(E e) {

//添加元素之前,先调用ensureCapacityInternal方法

ensureCapacityInternal(size + 1);  // Increments modCount!!(增量modCount)

//这里看到ArrayList添加元素的实质就相当于为数组赋值

elementData[size++] = e;

return true;

}

再来看看ensureCapacityInternal()方法,可以看到add()方法首先调用了ensureCapacityInternal(size+1)

Java

运行代码复制代码

1

2

3

4

5

6

7

8

//得到最小扩容量

private void ensureCapacityInternal(int minCapacity) {

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

//获取默认的容量和传入参数的较大值(第一次的较大值是DEFAULT_CAPACITY=10,minCapacity=1)

minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);

}

ensureExplicitCapacity(minCapacity);

}

当要add进第一个元素时,minCapacity为1,在Math.max()方法比较后,minCapacity为10
ensureExplicitCapacity()方法

Java

运行代码复制代码

1

2

3

4

5

6

7

8

//判断是否需要扩容

private void ensureExplicitCapacity(int minCapacity) {

modCount++;

// overflow-conscious code

if (minCapacity - elementData.length > 0)

//调用grow()方法进行扩容,调用此方法代表已经开始扩容了

grow(minCapacity);

}

我们来仔细分析一下
1当我们要add进第一个元素到ArrayList时,elementData.length为0(因为还是一个空的list,里面还没有数据,所以没有进行扩容,默认扩容10),因为执行了ensureCapacityInternal()方法,所以minCapacity此时为10。此时,minCapacity - elemetData.length > 0(minCapacity=10,elemetData.length=0)成立,所以会进入==grow(minCapacity)==方法。
2当add第2个元素时,minCapacity为2,此时elementData.length(容量)在添加第一个元素后扩容成10了。此时,minCapacity - elementData.length > 0不成立,所以不会进入(执行)==grow(minCapacity)==方法。
3添加第3、4…到第10个元素时,依然不会执行==grow()==方法,数组容量都为10。知道添加第11个元素,minCapacity(为11)比elementData.length(为10)要大。进行grow方法进行扩容
4grow方法

Java

运行代码复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

private void grow(int minCapacity) {

// oldCapacity为旧容量,newCapacity为新容量

int oldCapacity = elementData.length;//(0,10,15)

//将oldCapacity右移一位,其效果相当于oldCapacity/2;

// 我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍

int newCapacity = oldCapacity + (oldCapacity >> 1);

// 然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么久把最小需要容量当作数组的新容量

if (newCapacity - minCapacity < 0)

newCapacity = minCapacity;

//判断新容量是否大于集合的最大容量(一般大不了)

if (newCapacity - MAX_ARRAY_SIZE > 0)

newCapacity = hugeCapacity(minCapacity);

// 给elementData从新赋值(10,15)

elementData = Arrays.copyOf(elementData, newCapacity);

}

int newCapacity = oldCapacity + (oldCapacity >> 1),所以 ArrayList 每次扩容之后容量都会变为原来的 1.5 倍!
“>>”(移位运算符):>>1 右移一位相当于除2,右移n位相当于除以 2 的 n 次方。这里 oldCapacity 明显右移了1位所以相当于oldCapacity /2。对于大数据的2进制运算,位移运算符比那些普通运算符的运算要快很多,因为程序仅仅移动一下而已,不去计算,这样提高了效率,节省了资源
通过例子探究一下grow()方法
当add第一个元素时,oldCapacity为0,经比较后第一个if判断成立,newCapacity = minCapacity(为10)。但是第二个if判断不会成立,即newCapacity不比MAX_ARRAY_SIZE大,则不会进入hugeCapacity方法。数组容量为10,add方法中return true,size增为1。
当add第11个元素进入grow方法时,newCapacity为15,比minCapacity(为11)大,第一个if判断不成立。新容量没有大于数组最大size,不会进入hugeCapacity方法。数组容量扩为15,add方法中rerurn,true,size增为11。
以此类推…这里补充一点比较重要,但是容易被忽视掉的知识点:
java中的length属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了length这个属性。
java中的length() 方法是针对字符串说的,如果想看这个字符串的长度则用到 length() 这个方法。
java中的size() 方法是针对泛型集合说的,如果想看这个泛型有多少元素,就调用此方法类查看!


相关文章
lyL
|
22小时前
|
Java 测试技术 Linux
生产环境发布管理
本文介绍大型团队中基于自动化部署平台的多环境发布流程,涵盖DEV、TEST、PRE、PROD各环境职责,结合CI/CD实现高效部署与日志追踪,提升发布效率与系统稳定性。
lyL
22 0
|
14小时前
|
SQL 运维 分布式计算
如何做好SQL质量监控
SLS推出用户级SQL质量监控功能,集成于CloudLens for SLS,提供健康分、服务指标、运行明细、SQL Pattern分析及优化建议五大维度,助力用户全面掌握SQL使用情况,提升日志分析效率与治理能力。
|
16小时前
|
敏捷开发 Java 测试技术
为什么要单元测试
本文探讨单元测试的重要性,指出其非但不拖慢进度,反而是提升研发效率、保障代码质量与系统稳定性的关键。通过解析测试金字塔、常见误区及反模式,倡导开发者重视并践行单元测试。
|
21小时前
|
敏捷开发 Java 测试技术
为什么要单元测试
刹⻋是降低了⻋速还是提升了⻋速?我们通常认为写单测费⼒耗时、耽误研发进度,仿佛在给项⽬“踩刹⻋”。⼤家不妨带着这个问题往下看,详细聊聊为什么单元测试可以让软件开发跑得更快。 什么是单元测试 ⼤家对于单测应该并不陌⽣,截取⼀段维基百科的定义帮⼤家唤醒⼀下记忆: 在计算机编程中,单元测试(Unit Testing)⼜称为模块测试,是针对程序模块(软件设计的最⼩单位)来进⾏正确性检验的测试⼯作。 单元测试的理念其实⼀直是编程的⼀部分。我们第⼀次编写计算机程序时,肯定会输⼊⼀些样本数据,查看其是否按照你的期望执⾏。如果结果不符合预期,你肯定在代码⾥穿插过⼤量的System.out.println
lyL
|
22小时前
|
SQL 运维 分布式计算
如何做好SQL质量监控
SLS推出用户级SQL质量监控功能,集成于CloudLens for SLS,提供健康分、服务指标、运行明细、SQL Pattern分析及优化建议五大维度,助力用户全面掌握SQL使用情况,提升日志分析效率与服务质量。
lyL
16 0
|
17小时前
|
Java
ArrayList扩容机制
ArrayList初始化容量为0,添加第一个元素时触发扩容,minCapacity设为10,执行grow(),容量从0扩至10。后续添加元素至第10个时均不扩容。添加第11个时,minCapacity为11,大于当前容量10,再次调用grow(),新容量为15。grow()通过比较minCapacity与旧容量的1.5倍决定新容量,不超过最大值。注意:length用于数组,length()用于字符串,size()用于集合。
lyL
|
18小时前
|
5G 定位技术
练手需求
根据需求完成全景图数据读取接口开发,实现表结构设计、0-1搭建、三次架构编码及JUnit测试,3小时内完成。接口URL:/gis/panorama/findCmCell,POST方式,传参time(日期)和rruSerialNo,返回锁定小区列表信息。
lyL
21 0
|
14小时前
|
Java 测试技术 Linux
生产环境发布管理
本文介绍大型团队如何通过自动化部署平台实现多环境(dev/test/pre/prod)发布管理,涵盖各环境职责、CI/CD流程、分支发布、容器化部署及基于Skywalking的日志链路追踪,提升发布效率与系统稳定性。
|
18小时前
|
人工智能 安全 数据挖掘
2026年企业级BI系统建设方案:构建智能数据驱动决策新体系
企业数字化转型深化,数据成核心生产要素。Gartner报告显示,AI赋能、全场景协同的BI工具占主流。瓴羊Quick BI凭借“智能小Q”与阿里生态协同,连续六年入选Gartner魔力象限,助力企业实现数据驱动决策。本文剖析10大BI工具竞争力,提供选型指南。
|
14小时前
|
SQL 运维 分布式计算
如何做好SQL质量监控
本文介绍如何通过CloudLens for SLS实现SQL质量监控,帮助用户全面掌握SQL使用情况。涵盖健康分、服务指标、运行明细、SQL Pattern分析及优化建议五大维度,助力识别性能瓶颈、优化资源使用,提升日志分析效率与治理能力。
 如何做好SQL质量监控

热门文章

最新文章