ArrayLiat集合底层原理
ArrayList定义在Java.util包下
ArrayList底层是数组结构的
- 利用空参创建的集合,在底层创建一个默认长度为0的数组,数组名叫elementData,与此同时在底层还有一个成员变量叫size,用来记录元素个数
- 添加第一个元素时,底层会创建一个新的长度为10的数组,数组名叫elementData,将元素放到0索引的位置,同时size++
- size这个变量有两层含义
- 元素个数
- 下次存入位置
- size这个变量有两层含义
- 存满时,会扩容1.5倍,将数据拷贝到新数组中
- 再次存满时,再扩容1.5倍
- 如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准
//这玩意就是一个空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//底层就是一个叫elementData的数组
transient Object[] elementData;
private int size;
//空参构造,将空数组传给elementData
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//添加元素
public boolean add(E e) {
modCount++;
add(e, elementData, size);//调用了重载的add方法
return true;
}
//重载的add方法,private修饰,只能在类中调用
//传入的参数分别为 要添加的元素、集合底层的名字、集合的长度/当前元素应存入的位置
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length) { //判断数组是否存满
elementData = grow(); //若存满,调用grow方法扩容
}
elementData[s] = e; //添加元素到数组中
size = s + 1; //size++
}
//add方法中的调用grow方法
private Object[] grow {
return grow(size + 1); //再次调用重载的grow方法进行扩容
}
//重载的grow方法
private Object[] grow(int minCapacity) { //将需要扩容后的数组最小长度作为参数传入方法
int oldCapacity = elementData.length; //记录原数组的长度
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //如果原数组长度不为0或不为空
//调用了ArraySupport.newLength方法计算数组的最新长度
//传入的参数分别为 原数组的长度、需要扩容的最小长度、默认扩容长度(这里右移一位就是除以2)
int newCapacity = ArraySupport.newLength(oldCapacity, minCapacity - oldCapacity, oldCapacity >> 1);
return elementData = Arrays.copyOf(elementData, newCapacity); //调用Arrays.copyOf方法拷贝数组并返回
} else { //如果原数组长度为0或为空
return elementData = new Object[Math.max(DEFAULT_ minCapacity)]; //创建一个新的数组并返回,数组的长度为10(常量)和需要扩容后的数组最小长度之间的最大值
}
}
private static final int DEFAULT_CAPACITY = 10;
//ArraySupport.newLength方法 计算数组的最新长度
//传入的参数分别为 原数组的长度、需要扩容的最小长度、默认扩容长度(原数组长度的一半)
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
//计算数组的最新长度 原长度加上 需要扩容的最小长度和默认扩容长度之间的最大值
int prefLength = oldLength + Math.max(minGrowth, prefGrowth);
//如果这个最新长度大于0且不超过数组最大长度(21亿多)
if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
return prefLength; //返回
} else {
return hugeLength(oldLength, minGrowth);
}
}