根据jdk8中ArrayList源码注释得知: 对ArrayList源码注释进行阅读: Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List 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 Vector, except that it is unsynchronized.)
ArrayList是实现了List接口的可变长数组,实现了所有可选的list操作,包括null在内的所有元素都被许可。除了实现list接口之外呢,在其内部有一个用于存储list的数组,ArrayList为此提供了一些方法来改变这个数组的长度。(ArrayList与Vector类似,前者是线程不安全的。)
The size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, that is, adding n elements requires O(n) time. All of the other operations run in linear time (roughly speaking). The constant factor is low compared to that for the LinkedList implementation.
像size、isEmpty、get、set、iterator、listIterator这些方法运行时间是一个常量。 add操作运行就是一个平摊的常量时间,add n个元素就需要O(n)的时间。 粗略地说,其余操作方法运行时间基本是线性的。 这个常量因子比起LinkedList的实现要低一些。
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.
每个ArrayList的实例都有一个capacity,它决定了list用于存储元素的数组的大小,capacity至少有list一样大小,当有元素被添加到ArrayList的时候,capacity会自动变大。这个变大的算法细节中,指定了添加元素需要常量平摊的时间花费。
An application can increase the capacity of an ArrayList instance before adding a large number of elements using the ensureCapacity operation. This may reduce the amount of incremental reallocation.
一旦使用ensureCapacity指定了capacity大小,ArrayList将不能在应用中进行自动扩容。这可能减少增量重新分配。
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list.
注意这个实现是线程不安全的,如果多个线程并发访问ArrayList实例,而且至少有一个线程修改了list结构,一定要进行外部的同步。(进行添加元素或删除元素操作,或明确调整了支持数组的的大小,都是属于修改结构;仅仅是给一个元素设值则不算修改结构)通常通过对某些自然封装了list的对象进行同步来完成。
If no such object exists, the list should be “wrapped” using the {@link Collections#synchronizedList Collections.synchronizedList} method. This is best done at creation time, to prevent accidental unsynchronized access to the list:
List list = Collections.synchronizedList(new ArrayList(…));如果没有这样的对象,list应该通过 Collections的synchronizedList方法来“包裹”起来。为了防止预料之外的对list的并发访问,最好在创建时完成。
The iterators returned by this class's {@link #iterator() iterator} and {@link #listIterator(int) listIterator} methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own {@link ListIterator#remove() remove} or {@link ListIterator#add(Object) add} methods, the iterator will throw a {@link ConcurrentModificationException}. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
当list的迭代器对象被创建之后,list在进行除了通过ListIterator的add和remove方法之外的任何修改结构的操作时,迭代器将会抛出异常ConcurrentModificationException。因此在面对结构变化时,迭代器将无法工作。
Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw {@code ConcurrentModificationException} on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.
该方法返回在list中指定位置的元素。 ①:进行索引校验,判断指定位置是否超出了list的大小,如果超过则抛出异常IndexOutOfBoundsException:
/** * Checks if the given index is in range. If not, throws an appropriate * runtime exception. This method does *not* check if the index is * negative: It is always used immediately prior to an array access, * which throws an ArrayIndexOutOfBoundsException if index is negative. */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }②:返回数组中指定索引的元素:
@SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; }该方法用于将指定元素添加至list的末尾。 ①:找到ensureCapacityInternal方法:
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }在这里先对elementData进行了判断,如果为空,将minCapacity设为默认容量DEFAULT_CAPACITY:
/** * Default initial capacity. */ private static final int DEFAULT_CAPACITY = 10;找到ensureExplicitCapacity方法:
private void ensureExplicitCapacity(int minCapacity) { modCount++; ① // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); ② }①:这里对modCount进行了自增操作,我们看看modCount是什么:
/** * The number of times this list has been <i>structurally modified</i>. * Structural modifications are those that change the size of the * list, or otherwise perturb it in such a fashion that iterations in * progress may yield incorrect results. * * <p>This field is used by the iterator and list iterator implementation * returned by the {@code iterator} and {@code listIterator} methods. * If the value of this field changes unexpectedly, the iterator (or list * iterator) will throw a {@code ConcurrentModificationException} in * response to the {@code next}, {@code remove}, {@code previous}, * {@code set} or {@code add} operations. This provides * <i>fail-fast</i> behavior, rather than non-deterministic behavior in * the face of concurrent modification during iteration. * * <p><b>Use of this field by subclasses is optional.</b> If a subclass * wishes to provide fail-fast iterators (and list iterators), then it * merely has to increment this field in its {@code add(int, E)} and * {@code remove(int)} methods (and any other methods that it overrides * that result in structural modifications to the list). A single call to * {@code add(int, E)} or {@code remove(int)} must add no more than * one to this field, or the iterators (and list iterators) will throw * bogus {@code ConcurrentModificationExceptions}. If an implementation * does not wish to provide fail-fast iterators, this field may be * ignored. */ protected transient int modCount = 0;从上述注释第一句中,可以看出modCount 是指list产生结构变化的次数。 ②:将modCount 自增之后,进行了一次判断,minCapacity - elementData.length > 0,看list所需容量与存储数组相比,是否满足存储需要。如果minCapacity > elementData.length,即原有数组长度不够,就进行扩容操作。 找到grow方法:
/** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; 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); }提高容量来确保至少能存储使用最小容量参数指定的元素数量。
从这里的代码可以看出,newCapacity 是oldCapacity 的二分之三倍,扩容的部分是原容量的一半。 如果newCapacity 比minCapacity 小,将minCapacity 的值赋给newCapacity 。 如果newCapacity 比数组最大容量(Integer.MAX_VALUE - 8)还大,就进入了hugeCapacity方法:
private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }这里确保list容量最大不超过 Integer.MAX_VALUE。
回到扩容方法,minCapacity 通常是接近size大小的,最后一步,通过数组的copyOf方法将原数组的元素拷贝到新容量的数组上。 到这里ensureCapacityInternal方法执行完毕。
最后在存储数组elementData的末尾加上目标元素,然后顺便将size自增。
综合上述分析,我们可以总结下ArrayList在添加元素时做了哪些事。 1、如果list中的元素数组为空,则会建立一个默认容量为10的数组。来存储元素。 2、如果list中的元素数组不为空,当数组长度不满足需求时,会在原有数组长度的基础上进行扩容,扩容的部分是原有数组长度的一半。