注释是个好东西,首先我们通过源码里的注释来了解下这个集合的一些特性,直接粘贴+翻译(英文一般,借助Google翻译勉强读吧):
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.)
它是一个实现List接口的可变数组。实现了所有List的操作,并允许所欲元素包括null。除了实现List接口之外,它还提供了一些操作数组内部元素的方法。
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.
有长度、非空判断等一些操作方法。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.
每个集合实例都有一个容量,这个容量大小是数组用来存放元素的,它通常至少是list的长度。当元素被增加到集合中它的容量是自增的。自增策略的细节不是超出添加元素....(意会。。)
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操作增加大量元素之前。这可能会减少递增式的再分配数量。
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
* {@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(...));
利用 Collections.synchronizedList来实现一个线程安全的集合(并发场景下我们可以用Java提供的并发类容器,详情自己查资料..)
* 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.
ArrayList采用了快速失败(fail-fast)的机制,通过记录modCount参数来实现。在面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。
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.
注意这个快速失败机制在迭代中并不能保证就是这样,通常来讲在未同步并发修改时它并不能提供任何硬性保证。快速失败机制会尽最大努力抛出一个ConcurrentModificationException。因此需要为这类问题编写一个依赖的异常,正确的除外。这种快速失败行为只适用于检查Bug。
(个人水平有限,海谅。。。。来看下代码部分)
- ArrayList继承和实现
- ArrayList的元素在哪里维护
底层使用Object类型的数组来维护元素,源码如下 :/** * Default initial capacity. 默认初始容量 */ private static final int DEFAULT_CAPACITY = 10; /** * Shared empty array instance used for empty instances. 空实例的共享空数组 */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * Shared empty array instance used for default sized empty instances. We * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when * first element is added. 共享一个空实例用以默认大小的空实例。我们将它与EMPTY_ELEMENTDATA区别开来, * 以便了解当一个元素添加时它膨胀了多少 */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** * The array buffer into which the elements of the ArrayList are stored. //ArrayList的元素存储在其中的数组缓冲区 * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ // 关于这个数组请转看 transient Object[] elementData; // non-private to simplify nested class access /** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size;
- 构造方法
1)构造一个默认容量为10的空数组(其实是在第一次add操作时初始化10个长度的)
2)构造一个指定初始容量的空数组/** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
/** * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity * is negative */ public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
For example: 3)构造一个包含指定元素集合的arrayList.只支持对象类型,不支持基本数据类型
/** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */ public ArrayList(Collection extends E> c) { elementData = c.toArray(); //转数组 if ((size = elementData.length) != 0) { //赋值并判断 // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
- 常用方法 以新增元素为例:
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
4.1 ensureCapacityInternal方法来保证内部容量循环中操作元素的办法
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //如果默认是空的数组,则最小容量在默认10和入参中选择最大的 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) //----如果数组的长度小于最小容量,则扩容 grow(minCapacity); //扩容方法 }
重点:Arrays.copyOf是新建一个newCapacity长度的新数组,并拷贝elementData数组。为了避免多次复制新建数组,应该提前预估长度,固定长度则可选用数组。/** * 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; //---- 移位运算符,效率高。 相当于newCapacity =oldCapacity + 0.5 * oldCapacity 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); //-- }
- 总结 :
了解源码的目的就是为了更好地利用jdk提供的类,详情 转看