从日常代码看ArrayList的执行流程
第一步:我们初始化一个 ArrayList;然后添加一个元素,代码如下
public class ArrayListTest {
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("aa");
}
}
ArrayList的构造函数和方法有三个,一个是带有初始大小的ArrayList,一个传入Collection<? extends E>,另外一个空参。
我们调用空参构造函数,构造函数中初始化了一个 空的数组。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
第二步: 添加元素 ,上源码:
private int size;
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
因为当声明一个int值时,他的值等于0,我们就可以看到传入ensureCapacityInternal 为1
private static final int DEFAULT_CAPACITY = 10;
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
判断 目前的elementData 是不是还是空的数组,如果是空的,我们第一步要决定这个数组的初始化大小了。上一步得到 minCapacity=1 ,因为小于DEFAULT_CAPACITY ,所以我们初始化大小为10
protected transient int modCount = 0;
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
因为是新的元素,所以我们的元素为0个,然后++,变成了一个,因为我们传入的是10 ,然后执行 grow 方法,来初始化数组的长度了,插一个transient的介绍:序列化的时候,将不需要序列化的属性前添加关键字transient即可
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; // value=0
int newCapacity = oldCapacity + (oldCapacity >> 1);
//newCapacity =0 当数组需要扩容时,上步newCapacity长度为原来的1.5倍 (注:10>>1=10/2)
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity; //newCapacity=10
if (newCapacity - MAX_ARRAY_SIZE > 0) //不进入if语句
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); //ok ,初始化大小10的数组。
}
从这个方法中我们中我们可以得到初始化的数组为10了。