1.概述
Resizable-array implementation of the <tt>List</tt> interface. Implements
all optional list operations, and permits all elements, including
<tt>null</tt>. In addition to implementing the <tt>List</tt> interface,
this class provides methods to manipulate the size of the array that is
used internally to store the list. (This class is roughly equivalent to
<tt>Vector</tt>, except that it is unsynchronized.)
从这段注释中,我们可以得知ArrayList是一个动态数组,实现了List接口以及list相关的所有 方法,它允许所有元素的插入,包括null。另外,ArrayList和Vector除了线程不同步之外,大 致相等.
2. 属性值
//默认容量的大小
private static final int DEFAULT_CAPACITY = 10;
//空数组常量
private static final Object[] EMPTY_ELEMENTDATA = {};
//默认的空数组常量
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//存放元素的数组,从这可以发现ArrayList的底层实现就是一个Object数组
transient Object[] elementData;
//数组中包含的元素个数
private int size;
//数组的最大上限
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
3. 以一个简单例子说明源码看下底层的原理
List<String> list = new ArrayList<>();
list.add("flysun55");
/**
* Constructs an empty list with an initial capacity of ten.
* elementData是一个大小为0的空数组
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//添加元素在末尾
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!! 第一次添加元素时 0 + 1
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
//判断是否是空数组 即是否是第一次add操作
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//第一次添加元素时初始容量为10
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity)
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code 扩容判断,但第一次add添加时,会进入此判断并默认初始ArrayList大小为10
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//grow方法是在数组进行扩容的时候用到的,
private void grow(int minCapacity) {//第一次add 时10
// overflow-conscious code
int oldCapacity = elementData.length;
//ArrayList每次扩容都是扩1.5倍,调用Arrays类的copyOf,把元素重新拷贝到一个新的数组中去
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)//第一次add 进
newCapacity = minCapacity;//10
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
4. 结论
add方法,在插入元素之前,它会先检查是否需要扩容,然后再把元素添加到数组中最后一个元素的后面。在ensureCapacityInternal方法中,我们可以看见,如果当elementData为空数组时,它会使用默认的大小去扩容。
所以说,通过无参构造方法来创建ArrayList时,它的大小其实是为0的,只有在使用到的时候,才会通过grow方法去创建一个大小为10的数组。
第一个add方法的复杂度为O(1),虽然有时候会涉及到扩容的操作,但是扩容的次数是非常少的,所以这一部分的时间可以忽略不计。
如果使用的是带指定下标的add方法,则复杂度为O(n),因为涉及到对数组中元素的移动,这一操作是非常耗时的。
- ArrayList创建时的大小为0;当加入第一个元素时,进行第一次扩容时,默认容量大小为10。
- ArrayList每次扩容都以当前数组大小的1.5倍去扩容。