JDK8 ArrayList源码分析

36 阅读3分钟

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操作提高一个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. If no such object exists, the list should be "wrapped" using the Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list: 注意:这个实现是非线程安全的。如果多个线程同时访问一个ArrayList实例,并且至少一个线程在结构上修改这个list,它必须在外部被同步。(结构性的修改是指任何添加或删除一个或多个元素、调整内部数组大小;仅仅只是设置一个元素的值不是一个结构性的修改。)这通常是通过同步某一对象自然地封装这个list来实现的。如果没有这样的对象存在,这个list应当被用Collections.synchronizedList方法来包装。为了预防意外的非同步访问这个list,这最好在创建时进行: List list = Collections.synchronizedList(new ArrayList(...));

The iterators returned by this class's iterator and 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 remove or add methods, the iterator will throw a 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. 这个类的iterator方法和listIterator方法返回的迭代器是fail-fast的:如果在迭代器被创建后这个list被在结构上改变了,除非是通过迭代器自身的remove或者add方法,这个迭代器将会抛出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 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. 注意:事实上一个迭代器的fail-fast行为不能够被保证,通常来说,当出现非同步的并发修改时不可能作出任何严格的保证。Fail-fast迭代器尽最大努力抛出ConcurrentModificationException。因此,写一个基于这个异常的正确性的程序是错误的:fail-fast行为应当只是被用来定位问题。

2. elementData不会被序列化

=====================

transient Object[] elementData;

复制代码

从变量声明情况来看,如果序列化ArrayList实例,elementData存储的数据是不会保存下来的,实际开发中后端暴露的api返回的对象中常常包含ArrayList,这个数据是怎么传递的?具体情况待验证。

3. 内部数组elementData扩容

=====================

private static final int DEFAULT_CAPACITY = 10;

复制代码

默认容量是10。

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);

}

复制代码

自动扩容后容量是原容量的1.5倍。

指定扩容也会先检测自动扩容是否满足,不满足再按照指定容量扩容。

类注释上提到的ensureCapacity方法最终也是调用的这个grow方法。当然,会先作扩容必要性的判断。