浅析ArrayList源码(JDK1.8)

ArrayList是基于数组实现的List,数组的容量可以改变。ArrayList中允许存放null元素。

ArrayList是unsynchronized的,而Vector是synchronized的。这是两者的主要区别,除此之外两者大致相似。

在ArrayList中,size(), get(),isEmpty(), set(),iterator(), 和listIterator()等方法的时间复杂度都是常数级别的。add操作需要的时间平均下来也是常数级别,也就是说,添加n个元素的时间复杂度为O(n)。所有其他操作基本上都以线性时间运行。 与LinkedList的实现相比,ArrayList的常数因子较低。

同样的,ArrayList的iterator具有fail-fast机制。

下面看源码:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

由声明可以看出,ArrayList继承自AbstractList,实现了List等接口。

    //默认初始容量为10
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 所有新建的空的实例对象共享的一个空的数组实例
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 所有新建的具有默认size的空的实例对象共享的一个空的数组实例
     * 与EMPTY_ELEMENTDATA的区别在于,使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA可以知道当
     * 添加第一个元素时,数组容量应该扩大为多少
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

用于存储元素的数组elementData,数组的长度就是ArrayList的容量。任何一个空的ArrayList,如果它的elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,那么,在添加第一个元素时,它的容量会被扩充为默认容量: 

transient Object[] elementData; // non-private to simplify nested class access

存放的元素的数量为size:   

//The size of the ArrayList ().
private int size;

ArrayList具有的构造函数如下:

根据制定的初始容量新建一个ArrayList,如果制定容量大于0,则新建一个数组,若容量指定为0,直接另elementData=EMPTY_ELEMENTDATA,若小于0就会抛出异常。

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

默认的构造函数如下,将elementData指向空的数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA,但是,当添加第一个元素时,容量将被扩容为默认初始容量(10)。

public ArrayList() {
     this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

还可以根据另外一个容器来初始化一个ArrayList,将指定容器中的元素按照其iterator迭代的顺序取出来并依次添加到ArrayList中:

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

方法trimToSize的作用是,将ArrayList的容量(即数组的长度)设置为List中已经存放的元素的数量(size)。通过此操作,可以将ArrayList的存储空间最小化。

public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = (size == 0)
          ? EMPTY_ELEMENTDATA
          : Arrays.copyOf(elementData, size);
    }
}

方法ensureCapacity的作用是在必要的情况下增加ArrayList的容量以确保ArrayList中能够容纳至少minCapacitiy的元素。

public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
 }

size()、isEmpty()和contains()方法的实现:

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

indexOf()方法:在数组存放的元素中从前到后查找元素o第一次出现时的下标(允许重复元素),如果元素不存在,返回-1:

    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

lastIndexOf()方法:在数组存放的元素中从后往前查找元素o第一次出现时的下标(允许重复元素),如果元素不存在,返回-1:

    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

get()方法的实现:

    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

set()方法:替换相应位置上的元素

    public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

add()方法添加元素:

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

在指定位置上添加元素,如果该位置上已经有元素了,则将该元素及其之后的元素右移:

    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++;
    }

删除指定位置上的元素,其后的元素全都左移一个位置:

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

删除指定元素o在ArrayList中从前往后出现的第一个,如果ArrayList中没有存放该元素,则不做任何其他操作。如果存在且删除了,返回true;如果不存在该元素,返回false。

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

移除List中所有的元素:

    public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

迭代器iterator:

    public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

 

猜你喜欢

转载自blog.csdn.net/sun_lm/article/details/81181749