1,首先我们看一段代码
ArrayList list = new ArrayList();//1
list.add(1);//2
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
list.add(2,3.1);
System.out.println(list);
我们平时都是直接喜欢new ArrayList(),用无参构造来实例化ArrayList,那么它的初始化容量是多少呢?
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
从上面的代码可以看出,无参构造来实例化的ArrayList,其实是一个空数组。
当我们代码走到2处,即list.add(1),
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 扩容
//size为已使用的数组大小,此时为0
elementData[size++] = e;
return true;
}
再看ensureCapacityInternal(size + 1) 源码
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
第一次添加,size = 0,因此minCapacity=1,elementData为一个大小为0的数组。进入calculateCapacity(elementData, minCapacity)
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
上面说过,初始化的时候ArrayList,this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;因此会进入到Math.max(DEFAULT_CAPACITY, minCapacity)方法,这里就可以知道,为什么ArrayList的初始化容量为10了,因为DEFAULT_CAPACITY=10。
//默认初始化容量
private static final int DEFAULT_CAPACITY = 10;
接着到上一层的ensureExplicitCapacity(int minCapacity)方法,这时minCapacity=10了。进入此方法:
//minCapacity=1
private void ensureExplicitCapacity(int minCapacity) {
//modCount为数组修改的次数
modCount++;
// minCapacity - elementData.length相当于10-0>0(仅是第一次添加元素的时候)
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
由于大于0,进入 grow(minCapacity),minCapacity=10
private void grow(int minCapacity) {
// 现在数组的长度,为0
int oldCapacity = elementData.length;
//扩容后的长度
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//复制,返回扩容后的数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
Arraylist每次都按照1.5倍扩容就是来自算法oldCapacity >> 1,由于oldCapacity=0,所以,newCapacity=0,
接着if (newCapacity - minCapacity < 0)满足条件,newCapacity=10,
接着扩容数组elementData = Arrays.copyOf(elementData, newCapacity)后,elementData就是一个容量为10的数组了。
扩容完后就是赋值了,返回到最开始的代码:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
//赋值
elementData[size++] = e;
return true;
}
现在,一个添加操作就已经完成了。从代码可以看出,添加操作每次都会根据minCapacity - elementData.length > 0条件判断是否需要扩容,不需要则直接赋值操作。
我们再来看一下ArrayList的属性
//无参初始化默认容量
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;
我们会发现有两个空数组EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA,这两个有啥区别??
DEFAULTCAPACITY_EMPTY_ELEMENTDATA是ArrayList()时使用,
EMPTY_ELEMENTDATA是ArrayList(0)时使用,并且走的时1.5倍的扩容。
并且写代码别ArrayList list = new ArrayList(0);这样初始化,因为这样初始化,添加元素会频繁扩容。
以上为添加方法的源码讲解。