ArrayList底层源码分析
底层原理
-
创建使用ArrayList<>()创建空对象的时候,会在底层创建一个长度为0的数组。该数组的名称为
elementData
,定义变量size
size
变量有两层含义- ① 表示元素的个数,也就是集合的长度
- ② 表示下一个元素的存入位置
-
添加第一个元素之后,size++,同时底层会创建一个新的长度为
DEFAULT_CAPACITY
=10的数组 -
扩容机制1:
- 当存满的时候,会创建一个新的数组,新数组的长度是原来的1.5倍,也就是长度为15。再把所有的元素拷贝到新数组中。如果继续添加数据,这个长度为15的数组也满了,那就会继续按照相同的方式扩容1.5倍。
-
扩容时机2:
- 当使用例如
addAll()
这样的方法一次性添加多个数据,扩容1.5倍的方法不够用时,则以扩容的实际大小为准。
成员变量:
- 当使用例如
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
构造方法:
//无参构造器,最开始创建的是空数组,当添加第一个元素时初始化容量为10。
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//指定初始化容量,为0的话则创建空数组。
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);
}
}
//传入一个集合,将该集合中的元素存到ArrayList中。
public ArrayList(Collection<? extends E> c) {
Object[] a = c.toArray();
if ((size = a.length) != 0) {
if (c.getClass() == ArrayList.class) {
elementData = a;
} else {
elementData = Arrays.copyOf(a, size, Object[].class);
}
} else {
// replace with empty array.
elementData = EMPTY_ELEMENTDATA;
}
}
add方法
- add(E e):直接在ArrayList尾部追加元素
- add(int index, E element):在指定index位置追加元素
public boolean add(E e) {
//记录结构上被修改的次数
modCount++;
add(e, elementData, size);
return true;
}
private void add(E e, Object[] elementData, int s) {
//如果当前数组长度等于ArrayList容量则扩容
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
public void add(int index, E element) {
//检查下标是否越界
rangeCheckForAdd(index);
modCount++;
final int s;
Object[] elementData;
//如果当前数组长度等于ArrayList容量则扩容
if ((s = size) == (elementData = this.elementData).length)
elementData = grow();
//把index位置及其后的元素向后移动一位
System.arraycopy(elementData, index,
elementData, index + 1,
s - index);
elementData[index] = element;
size = s + 1;
}
grow()方法
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//获取新容量大小
//oldCapacity右移一位即是原长度的一半,ArraysSupport.newLength方法选择minCapacity - oldCapacity或oldCapacity >> 1较大的一方与oldCapacity相加。
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
//将之前元素迁移到新数组,返回按照新容量扩容后的数组
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
//如果容量为0,则按照默认容量创建一个数组。
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
private Object[] grow() {
return grow(size + 1);
}