当前位置:网站首页>ArrayList的扩容机制
ArrayList的扩容机制
2022-06-10 20:55:00 【Li_XiaoJin】
今天了解一下 ArrayList 的扩容机制。
1. 先看下 ArrayList 的构造方法,有三种
(1)带初始容量参数的构造函数,用户可以自己定义容量
(2)默认构造函数,使用初始容量10构造一个空列表(无参数构造)
(3)构造包含指定collection元素的列表,这些元素利用该集合的迭代器按顺序返回
源码如下:
/**
* 默认初始化大小,10
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 用于空实例的共享空数组实例
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 用于默认大小的空实例的共享空数组实例。我们将其与空的元素数据区分开来,以了解添加第一个元素时要添加多少
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* ArrayList 的大小
*/
private int size;
/**
* 带初始容量参数的构造函数。(用户自己指定容量)
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* 默认构造函数,使用初始容量10构造一个空列表(无参数构造)
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 构造包含指定collection元素的列表,这些元素利用该集合的迭代器按顺序返回
*如果指定的集合为null,throws NullPointerException。
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
2. 通过源码分析 ArrayList 的扩容机制
通过以上,可以发现以无参数构造方法创建 ArrayList 时,实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时,才真正分配容量。即向数组中添加第一个元素时,数组容量扩为10
接下来分析一下添加元素和扩容的过程。
当调用add(E e)方法进行添加元素时,首先会调用 ensureCapacityInternal f方法
/**
* 将指定的元素追加到此列表的末尾
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 增加 modCount!!
elementData[size++] = e;
return true;
}
分析 ensureCapacityInternal 方法,当添加第一个元素时,size为0,得到minCapacity为1,判断数组的数据是不是空,如果是空将传进来的值和默认大小值进行比较,获取两个的最大值,当前可以得到 minCapacity变为10。然后再执行 ensureExplicitCapacity 方法,判断是否需要扩容。
/**
* 得到最小扩容量
* @param minCapacity
*/
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 获取默认容量和传进来参数的最大值
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
当插入的是第一个元素时,elementData.length为0,此时minCapacity为10,10>0,需要进行扩容,执行grow方法,扩展后的容量为10。 当插入的是第2至第10个元素时,minCapacity - elementData.length > 0 就不会成立,不会执行grow扩容操作,当到了第11个元素的时候就会开始扩容。
/**
* 判断是否需要扩容
* @param minCapacity
*/
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 当要插入的元素下标索引超过原有长度时,进行扩容
if (minCapacity - elementData.length > 0)
// 进行扩容
grow(minCapacity);
}
当插入的是第一个元素时,minCapacity为10,此时elementData.length=0,故 int newCapacity = oldCapacity + (oldCapacity >> 1); 计算后得到的值还是0;所以 newCapacity - minCapacity < 0 成立,newCapacity = minCapacity;第一次扩容的容量为10。
扩容的机制如下: 首先获取数组的旧容量,然后计算新容量的值,计算使用位运算,将其扩容至原来的1.5倍。 得到新容量的值后,校验扩容后的容量是否大于需要的容量,如果小于,则把最小需要容量当作扩容后的新容量。并确保扩容后的容量不超过数组能设置的最大大小值。 最后将老数组的数据复制到新的数组中。
/**
* 数组的最大大小分配。
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 增加容量,以确保它至少可以容纳指定的元素数。(扩容核心)
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// 获取旧容量
int oldCapacity = elementData.length;
// 使用位运算,扩容1.5倍,得到新容量
// >> 1 等价于 /2
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 校验扩容后的容量是否大于需要的容量,如果小于,则把最小需要容量当作扩容后的新容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 确保扩容后的容量不超过数组能设置的最大大小值
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
// 如果新容量大于最大容量,则新容量为 Integer.MAX_VALUE;否则为 Integer.MAX_VALUE - 8
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
画了个图,不是很准确,大概可以看
参考:
Copyright: 采用 知识共享署名4.0 国际许可协议进行许可 Links:https://lixj.fun/archives/arraylist的扩容机制
边栏推荐
- 数组 两数之和
- MySQL insère les résultats de la requête dans une autre table
- Array rotate array
- Constructing the implementation strategy of steam education for children
- 磁盘序列号,磁盘ID,卷序列号的区别
- 2022 - 06 - 09 rk817 PMU Battery Temperature Detection
- CentOS7环境下MySQL8常用命令小结
- [1024 ways to play windows azure] 75 Fast cloud database migration seamlessly migrate alicloud RDS SQL server to azure SQL databas
- String analysis and use
- 19 MySQL optimizations commonly used in projects
猜你喜欢

JS anchor positioning can extend many functions

Understanding of related concepts of target detection

Principle of gravure overprint and factors affecting overprint

ICML2022 | Sharp-MAML:锐度感知的模型无关元学习

C language - quick sorting in sorting

【Microsoft Azure 的1024种玩法】七十五.云端数据库迁移之快速将阿里云RDS SQL Server无缝迁移到Azure SQL Databas

Constructing the implementation strategy of steam education for children

Exec function of PHP
Super detailed tutorial for installing mysql8 in centos7 (no pit!)

Abbexa AML1 DNA binding ELISA Kit instructions
随机推荐
[nk] 牛客月賽51 G計算題
CentOS7安装MySQL8的超级详细教程(无坑!)
ThinkPHP v6.0.x反序列化漏洞复现
Ceph分布式存储集群Pool资源池的概念以及使用
报错解决Error parsing Mapper XML
Before we learn about high-performance computing, let's take a look at its history
Course design of imitation pottery ticket of wechat applet
19 MySQL optimizations commonly used in projects
用少儿编程思维塑造青少年领悟能力
Exec function of PHP
Detailed steps and actual records of SQL server2019 installation (available for hands-on test)
Cordova plugin /jpush phonegap Aurora push_ Local push_ Message push
数组 旋转数组
A WPF developed Print dialog box -printdialogx
C language ---6 first knowledge of selection statement, loop statement, function and array
Abbexa 1,3-dipalmitonin CLIA kit solution
Forward slash "/", backslash "\," escape character "\" and file path separator cannot be clearly remembered
JS anchor positioning can extend many functions
OC swift hybrid
oc swift 混编