public class Test1 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("abc");
list.add("hello");
list.remove("abc"); } }
这是最简单的一个添加操作,查看list.add源代码:
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return <tt>true</tt> (as specified by {@link Collection#add}) */ public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
其中size大小默认为0,所以传递过去的参数为1
查看ensureCapacityInternal()源代码
private void ensureCapacityInternal(int minCapacity) { if (elementData == EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }
而现在elementData为[],EMPTY_ELEMENTDATA也为[],所以进入if中,DEFAULTY_CAPACITY默认为10,minCapacity为1,所以minCapacity最终值为10
ensureExplicitCapacity源代码为:
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
当前elementData.length为0,所以进入if中直行grow(minCapacity)
/** * 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为大小的elementData属组。此时elementData中的元素为[null,null,null,null,null,null,null,null,null,null]
然后直行到最开始的代码 list.add("abc");
这时elementData中的元素为[abc, null, null, null, null, null, null, null, null, null]
接下来我们看看list.remove("abc")
/** * Removes the first occurrence of the specified element from this list, * if it is present. If the list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> * (if such an element exists). Returns <tt>true</tt> if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return <tt>true</tt> if this list contained the specified element */ public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; }
首先判断删除的元素是否为空,如果不为空那么执行fastRemove(index)
/* * Private remove method that skips bounds checking and does not * return the value removed. */ private void fastRemove(int index) { modCount++; 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 }
System.arraycopy(elementData, index+1, elementData, index,numMoved); elementData[--size] = null;
其中System.arraycopy()的意思是:public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) src:源数组; srcPos:源数组要复制的起始位置; dest:目的数组; destPos:目的数组放置的起始位置; length:复制的长度。
所以上面两句话的意思是将elementData中index之后的位置依次移动到前一个位置。效率非常低。
我们看看add(index,element)方法
/** * Inserts the specified element at the specified position in this * list. Shifts the element currently at that position (if any) and * any subsequent elements to the right (adds one to their indices). * * @param index index at which the specified element is to be inserted * @param element element to be inserted * @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }
与remove方法很相似。涉及到数组的移动。
所以ArrayList的添加和删除操作时,会涉及到数组的复制,这是个成本很高的操作。
优点:
ArrayList执行查询的速度是非常快的,因为底层采用的是数组,而数组是根据下标索引来执行查找的。