ArrayList源码分析

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&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;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执行查询的速度是非常快的,因为底层采用的是数组,而数组是根据下标索引来执行查找的。

 

posted @ 2015-09-09 17:16  vincent_duan  阅读(249)  评论(0编辑  收藏  举报