ArrayList 集合底层原理
查看 ArrayList 源码
在 IDEA 中按下 Ctrl + N
, 搜索 ArrayList
打开 ArrayList 源码, 按下 Alt + 7
查看 ArrayList
的 Structure
成员变量
我们主要关注以下两个成员变量
1 | transient Object[] elementData; |
成员变量 elementData
是一个数组, 用于存储 ArrayList
里面的元素, transient
标记该变量不应被序列化
size
存储了当前 ArrayList
中的元素数量, 同时标记了下次在 elementData
数组中添加元素的位置索引
空参构造方法
首先找到 ArrayList
的空参构造方法 ArrayList()
1 | public ArrayList() { |
DEFAULTCAPACITY_EMPTY_ELEMENTDATA
是一个空数组
1 | private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; |
空参构造方法将 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
赋值给 elementData
, 即首先创建了一个空数组
添加单个元素
1 | public boolean add(E e) { |
add(E e)
方法调用了 add(E e, Object[] elementData, int s)
方法
1 | private void add(E e, Object[] elementData, int s) { |
add(E e, Object[] elementData, int s)
方法首先判断当前 ArrayList
的 size
是否等于 elementData.length
的长度, 即 elementData
数组是否已经存满
如果 elementData
数组已经存满, 则调用 grow()
方法对数组进行扩容
1 | private Object[] grow() { |
grow()
方法调用 grow(int minCapacity)
方法, 并将 size + 1
作为当前所需的最小容量传入
1 | private Object[] grow(int minCapacity) { |
该方法首先记录当前的 elementData
数组长度, 即老容量
添加第一个元素
当添加第一个元素时, oldCapacity
等于 0, 所以执行
1 | return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)] |
创建一个新数组, 大小为 Math.max(DEFAULT_CAPACITY, minCapacity)
而 DEFAULT_CAPACITY = 10
, minCapacity
此时值为 1
1 | private static final int DEFAULT_CAPACITY = 10; |
所以添加第一个元素后, 数组扩容为 10
添加后续元素
当添加后续元素出现容量不够时, 会执行
1 | int newCapacity = ArraysSupport.newLength(oldCapacity, |
首先调用 ArraysSupport.newLength(int oldLength, int minGrowth, int prefGrowth)
方法计算新的数组长度
1 | public static int newLength(int oldLength, int minGrowth, int prefGrowth) { |
新的数组长度为 oldLength
即 oldCapacity
加上 Math.max(minGrowth, prefGrowth)
minGrowth = minCapacity - oldCapacity
, 添加单个元素时即为 1
prefGrowth = oldCapacity >> 1
, 即原来容量的一半
一般来说添加单个元素的情况下 prefGrowth
都要大于 minGrowth
, 所以新数组的长度为原来容量的 1.5 倍
所以添加单个元素时容量不够会扩充为原来容量的 1.5 倍
批量添加元素
调用 addAll
方法批量添加元素时, 如果数组容量不够, 同样会使用 grow()
方法扩容
1 | public boolean addAll(Collection<? extends E> c) { |
此时传入的参数是 size + numNew
, numNew
即使要批量添加的元素数量
此时当计算新容量执行到 int prefLength = oldLength + Math.max(minGrowth, prefGrowth);
时, minGrowth
即为 numNew
是可能大于 prefGrowth
, 即出现扩容 1.5 倍后容量仍然不够的情况
此时 prefLength = oldLength + numNew
, 即新容量等于原来容量加上要添加元素的数量
总结
1.利用空参构造器创建的 ArrayList
, 在底层会创建一个默认长度为 0 的数组 elementData
和一个成员变量 size 用于记录元素个数和下一次存储元素的位置
2.添加第一个元素时, 底层会创建一个新的长度为 10 的数组 elementData
, size ++
3.当添加单个元素容量不够时, 会扩容到原来容量的 1.5 倍
4.当批量添加元素时, 如果扩容到原来容量的 1.5 倍还放不下, 则新容量等于原来容量加上要添加元素的数量
- 标题: ArrayList 集合底层原理
- 作者: sun
- 创建于 : 2024-08-11 10:16:00
- 更新于 : 2024-08-11 02:17:49
- 链接: https://blog.csun.site/posts/f060681.html
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。