我们都知道Java的 ArrayList底层是封装了数组,通过数组来存储数据的。网上绝大多数的说法都是,当新建一个无参数的ArrayList时,数组的初始容量为10,然后每次容量不够时扩充为原先的1.5倍。我认为这种说法不够准确。关于new ArrayList() 的初始容量,在jdk1.6中的确是为10,然而在1.8中,如果只是new ArrayList() ,容量其实是0,当第一次通过add(E e)时,才扩充为10。
jdk1.8中,ArrayList的部分源码如下,列出了其参数
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
//序列版本号
private static final long serialVersionUID = 8683452581122892189L;
//默认初始容量
private static final int DEFAULT_CAPACITY = 10;
//被用于空实例的共享空数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};
//被用于默认大小的空实例的共享数组实例。其与EMPTY_ELEMENTDATA的区别是:当我们向数组中添加第一个元素时,知道数组该扩充多少。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* Object[]类型的数组,保存了添加到ArrayList中的元素。ArrayList的容量是该Object[]类型数组的长度
* 当第一个元素被添加时,任何空ArrayList中的elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA将会被
* 扩充到DEFAULT_CAPACITY(默认容量)。
*/
transient Object[] elementData; //非private是为了方便嵌套类的访问
// ArrayList的大小(指其所含的元素个数)
private int size;
无参数的构造方法如下,可以很明显的看出来,此时内部数组(也就是elementData)指向了常量DEFAULTCAPACITY_EMPTY_ELEMENTDATA,而这个常量在上面的代码中被定义为了空数组,长度为0。
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
大家应该都注意到了,第一段代码定义了两个空数组的常量,
EMPTY_ELEMENTDATA 和
DEFAULTCAPACITY_EMPTY_ELEMENTDATA
而这两个分别对应的构造方法是new ArrayList(0) 和 new ArrayList(),为什么要这么做,其实也是要在第一次add的时候以示区别,前者扩充后的容量为1,后者扩充后的容量是10。其中关键的代码如下,该代码计算了需要的容量。
private static int calculateCapacity (Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
当elementData为空数组,通过add(E e)传入的minCapacity为1(可以自己分析源码,这里不再具体说明)。若空数组为通过new ArrayList()创建的,即是elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,进入if条件中的代码,此时返回的容量是10(DEFAULT_CAPACITY)。若空数组是通过new ArrayList(0)创建的,会直接返回1(minCapacity)。