ArrayList源码分析
分析ArrayList源码主要从三个方面去翻阅:成员变量,构造函数,关键方法
以下源码都来源于jdk1.8
1 成员变量
DEFAULT_CAPACITY = 10; 默认初始的容量**(CAPACITY)
EMPTY_ELEMENTDATA = {}; 用于空实例的共享空数组实例 DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};用于默认大小的空实例的共享 空数组实例
Object[] elementData; 存储元素的数组缓冲区
int size; ArrayList的大小(它包含的元素数量)
2.构造方法(三个)
第一个构造是带初始化容量的构造函数,可以按照指定的容量初始化数组
第二个是无参构造函数,默认创建一个空集合
如果传入的容量大于0,就把一个长度为initialCapacity的的Object类型的数组初始化给elementData。
如果等于0,就给一个空数组。小于0,就报异常。
3.ArrayList源码分析
第一种情况:list中第一次添加数据
这种情况下,因为DEFAULT_CAPACITY = 10; 默认初始的容量(CAPACITY)
所以minCapacity会被赋值为较大的那个,也就是10。所以这里需要扩容(minCapacity(10) - elementData.length(0) > 0)进入扩容方法。
而进入扩容方法以后,会走第一次初始化数组长度那个if判断。
第二种情况:添加数据,但不需要扩容
这种情况下,根本不会走到扩容方法。
第三种情况:本次添加数据又需要扩容了
这种情况下,进入扩容方法以后,会扩容原来容量的1.5倍。最后还会进行数组拷贝,把原数组元素拷贝到,新增容量后的数组中!
4.结论
底层数据结构
ArrayList底层是用动态的数组实现的
初始容量
ArrayList初始容量为0,当第一次添加数据的时候才会初始化容量为10
扩容逻辑
ArrayList在进行扩容的时候是原来容量的1.5倍,每次扩容都需要拷贝数组
添加逻辑
确保数组已使用长度(size)加1之后足够存下下一个数据
计算数组的容量,如果当前数组已使用长度+1后的大于当前的数组长度, 则调用grow方法扩容(原来的1.5倍)
确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。
返回添加成功布尔值。