List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector 类,除了此类是不同步的。)
每个ArrayList实例都有一个容量,默认长度是10,ArrayList将添加的对象实质上
是保存在Object数组中,当保存对象的数量足够多且达到容器长度的最大值时,ArrayList
会进行扩容,每次扩容大小的当前数组长度的1/2,保存的元素可以是Null值 且可以重复。
主要特征:
1.未了保证容器有足够多的空间保存元素,又不浪费内存空间,每次添加元素都要确认长度是否
够用,如果达到容量上限,将进行扩容。
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); }
2.为了实现快速查询,类内部通过属性size来对元素进行计数
/** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size;
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
3.在删除元素时,所有在删除元素索引位置的其他元素将往左移,对性能有一定影响
/** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). * * @param index the index of the element to be removed * @return the element that was removed from the list * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; }
4.元素替换操作是指定索引位置,修改当前索引位置变量指向的内存地址,并未引起位置变动,所以性能是没问题的。
public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; }