// 默认的容量大小,10
private static final int DEFAULT_CAPACITY =10;
// 声明一个空的数组
private static final Object[] EMPTY_ELEMENTDATA ={};
// 声明一个空的数组。两个空的数组有什么区别呢? 简单来讲就是第一次添加元素时知道该 elementData 从空的构造函数还是有参构造函数被初始化的,以便确认如何扩容。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA ={};
// 真实存数据的数组
transient Object[] elementData;
// 实际元素的个数
private int size;
三个构造函数:
注释说构造一个容量大小为 10 的空的 list 集合,但构造函数了只是给 elementData 赋值了一个空的数组,其实是在第一次添加元素时容量扩大至 10 的。
elementData.getClass() != Object[].class为什么要有这个判断?
其实注释已经写的很清楚了,c.toArray不一定返回Object[],下面代码举例说明:
大家可以看下java.util.Arrays的源码,其内部有个ArrayList内部类,问题就出在这里,正常情况下我们直接new java.util.ArrayList().toArray()不会有任何问题,但是如果是Arrays.asList()就会产生返回不是Object[]数组的情况,所以源码有这个判断。
下面继续看添加元素的方法:
这里也可以看出ArrayList是线程不安全的:elementData[size++] = e,应为赋值和size++不是一个原子操作,是单独的两部,所以多线程的情况下就会有问题。
继续ensureCapacityInternal(size+1)方法:
calculateCapacity方法其实就是计算容量的,如果elementData={},就返回10和minCapacity的最大者,否则返回minCapacity。
ensureExplicitCapacity方法是关键,这是会有扩容的判断:grow(minCapacity)
当需要扩容的时候,就会走这个方法,什么时候扩容就不再赘述了,比较简单。扩容其实就是扩大为原来的1.5倍,即:newCapacity = oldCapacity +(oldCapacity >>1),如果newCapacity都大于MAX_ARRAY_SIZE = Integer.MAX_VALUE -8,
则:
这里有点争议,看代码是可以到Interge.MAX_VALUE,但是源码的MAX_ARRAY_SIZE的注释是下面这样的:
MAX_ARRAY_SIZE应该是为了防止内存溢出的,但是最大容量应该就是Integer.MAX_VALUE。
关于remove移除元素的方法就不说了,比较简单,大家自己看下就可以了。
下篇:LinkedList源码解读