ArrayList源码剖析

来源:互联网 发布:淘宝客移动建站app 编辑:程序博客网 时间:2024/05/17 07:33

先贴上源代码

使用的JDK版本:1.7.0_13

import java.util.Arrays;import java.util.Collection;import java.util.ConcurrentModificationException;import java.util.Iterator;import java.util.List;import java.util.ListIterator;import java.util.NoSuchElementException;import java.util.RandomAccess;/* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{    private static final long serialVersionUID = 8683452581122892189L;    //保存了当前对象的数据    private transient Object[] elementData;    private int size;    //由此可以看出,ArrayList实际上是已数组的形式保存的    public ArrayList(int initialCapacity) {        super();        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);        this.elementData = new Object[initialCapacity];    }    //默认大小为10    public ArrayList() {        this(10);    }    public ArrayList(Collection<? extends E> c) {        elementData = c.toArray();        size = elementData.length;        // c.toArray might (incorrectly) not return Object[] (see 6260652)        if (elementData.getClass() != Object[].class)            elementData = Arrays.copyOf(elementData, size, Object[].class);    }    //把数组大小调整为和size大小一致,可以节省空间    public void trimToSize() {        modCount++;        int oldCapacity = elementData.length;        if (size < oldCapacity) {            elementData = Arrays.copyOf(elementData, size);        }    }    /**     * Increases the capacity of this <tt>ArrayList</tt> instance, if     * necessary, to ensure that it can hold at least the number of elements     * specified by the minimum capacity argument.     *     * @param   minCapacity   the desired minimum capacity     */    public void ensureCapacity(int minCapacity) {        if (minCapacity > 0)            ensureCapacityInternal(minCapacity);    }    //在加入新对象时,需要先调用该方法,判断是否需要扩容    private void ensureCapacityInternal(int minCapacity) {        modCount++;        //如果下一个元素超过数组范围        if (minCapacity - elementData.length > 0)            grow(minCapacity);    }    //最大大小    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;    //扩容,这里是重点!!    private void grow(int minCapacity) {        int oldCapacity = elementData.length;        //每次扩容大小为当前大小的一半例如:当前:100,扩容后为150        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);    }    private static int hugeCapacity(int minCapacity) {        if (minCapacity < 0) // overflow            throw new OutOfMemoryError();        return (minCapacity > MAX_ARRAY_SIZE) ?            Integer.MAX_VALUE :            MAX_ARRAY_SIZE;    }    public int size() {        return size;    }    public boolean isEmpty() {        return size == 0;    }    public boolean contains(Object o) {        return indexOf(o) >= 0;    }    //顺序查找元素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;    }    //倒序找最后一个元素o    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;    }    //快照,这里是浅复制    public Object clone() {        try {            @SuppressWarnings("unchecked")                ArrayList<E> v = (ArrayList<E>) super.clone();            v.elementData = Arrays.copyOf(elementData, size);            v.modCount = 0;            return v;        } catch (CloneNotSupportedException e) {            // this shouldn't happen, since we are Cloneable            throw new InternalError();        }    }    //转成数组    public Object[] toArray() {        return Arrays.copyOf(elementData, size);    }    @SuppressWarnings("unchecked")    public <T> T[] toArray(T[] a) {        if (a.length < size)            // Make a new array of a's runtime type, but my contents:            return (T[]) Arrays.copyOf(elementData, size, a.getClass());        System.arraycopy(elementData, 0, a, 0, size);        if (a.length > size)            a[size] = null;        return a;    }    // Positional Access Operations    @SuppressWarnings("unchecked")    E elementData(int index) {        return (E) elementData[index];    }    //取值    public E get(int index) {        rangeCheck(index);        return elementData(index);    }    //放置值    public E set(int index, E element) {        rangeCheck(index);        E oldValue = elementData(index);        elementData[index] = element;        return oldValue;    }    //放入值    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++;    }    //移除某个位置的元素时,需要将后面的元素向前移动,调用了System.arraycopy函数,效率不是很高    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; // Let gc do its work        return oldValue;    }    //通过对象来删除    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);//这里index已经确定,不需要再进行边界检查了                    return true;                }        }        return false;    }    //快速删除,不再检查边界,并且不返回删除的值    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; // Let gc do its work    }    //全部置为null    public void clear() {        modCount++;        for (int i = 0; i < size; i++)            elementData[i] = null;        size = 0;    }    //此处先判断当前个数加c个数之和是否超标,超过则扩容,之和直接进行数组复制    public boolean addAll(Collection<? extends E> c) {        Object[] a = c.toArray();        int numNew = a.length;        ensureCapacityInternal(size + numNew);  // Increments modCount        System.arraycopy(a, 0, elementData, size, numNew);        size += numNew;        return numNew != 0;    }    //在某个位置插入一个Collection    public boolean addAll(int index, Collection<? extends E> c) {        rangeCheckForAdd(index);        Object[] a = c.toArray();        int numNew = a.length;        ensureCapacityInternal(size + numNew);  // Increments modCount        int numMoved = size - index;        if (numMoved > 0)            System.arraycopy(elementData, index, elementData, index + numNew,                             numMoved);        System.arraycopy(a, 0, elementData, index, numNew);        size += numNew;        return numNew != 0;    }    //范围删除    protected void removeRange(int fromIndex, int toIndex) {        modCount++;        int numMoved = size - toIndex;        System.arraycopy(elementData, toIndex, elementData, fromIndex,                         numMoved);        int newSize = size - (toIndex-fromIndex);        while (size != newSize)//需要将后面多出来的所有数据全部置为null            elementData[--size] = null;    }    //判断是否超标    private void rangeCheck(int index) {        if (index >= size)            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));    }    private void rangeCheckForAdd(int index) {        if (index > size || index < 0)            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));    }    private String outOfBoundsMsg(int index) {        return "Index: "+index+", Size: "+size;    }    public boolean removeAll(Collection<?> c) {        return batchRemove(c, false);    }    public boolean retainAll(Collection<?> c) {        return batchRemove(c, true);    }    private boolean batchRemove(Collection<?> c, boolean complement) {        final Object[] elementData = this.elementData;        int r = 0, w = 0;        boolean modified = false;        try {            for (; r < size; r++)                if (c.contains(elementData[r]) == complement)                    elementData[w++] = elementData[r];        } finally {            // Preserve behavioral compatibility with AbstractCollection,            // even if c.contains() throws.            if (r != size) {                System.arraycopy(elementData, r,                                 elementData, w,                                 size - r);                w += size - r;            }            if (w != size) {                for (int i = w; i < size; i++)                    elementData[i] = null;                modCount += size - w;                size = w;                modified = true;            }        }        return modified;    }    /**     * Save the state of the <tt>ArrayList</tt> instance to a stream (that     * is, serialize it).     *     * @serialData The length of the array backing the <tt>ArrayList</tt>     *             instance is emitted (int), followed by all of its elements     *             (each an <tt>Object</tt>) in the proper order.     */    private void writeObject(java.io.ObjectOutputStream s)        throws java.io.IOException{        // Write out element count, and any hidden stuff        int expectedModCount = modCount;        s.defaultWriteObject();        // Write out array length        s.writeInt(elementData.length);        // Write out all elements in the proper order.        for (int i=0; i<size; i++)            s.writeObject(elementData[i]);        if (modCount != expectedModCount) {            throw new ConcurrentModificationException();        }    }    /**     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,     * deserialize it).     */    private void readObject(java.io.ObjectInputStream s)        throws java.io.IOException, ClassNotFoundException {        // Read in size, and any hidden stuff        s.defaultReadObject();        // Read in array length and allocate array        int arrayLength = s.readInt();        Object[] a = elementData = new Object[arrayLength];        // Read in all elements in the proper order.        for (int i=0; i<size; i++)            a[i] = s.readObject();    }    public ListIterator<E> listIterator(int index) {        if (index < 0 || index > size)            throw new IndexOutOfBoundsException("Index: "+index);        return new ListItr(index);    }    public ListIterator<E> listIterator() {        return new ListItr(0);    }    public Iterator<E> iterator() {        return new Itr();    }    //定义ArrayList的游标    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        //这个变量很有意思,通过expectedModCount标记,当游标生成后,在遍历的过程中        //禁止再对ArrayList结构进行操作,例如添加、删除元素等,否则会报:ConcurrentModificationException        int expectedModCount = modCount;        public boolean hasNext() {            return cursor != size;        }        @SuppressWarnings("unchecked")        public E next() {            //检查该List是否在游标生成后被就改过            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();            }        }        final void checkForComodification() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();        }    }    /**     * An optimized version of AbstractList.ListItr     */    private class ListItr extends Itr implements ListIterator<E> {        ListItr(int index) {            super();            cursor = index;        }        public boolean hasPrevious() {            return cursor != 0;        }        public int nextIndex() {            return cursor;        }        public int previousIndex() {            return cursor - 1;        }        @SuppressWarnings("unchecked")        public E previous() {            checkForComodification();            int i = cursor - 1;            if (i < 0)                throw new NoSuchElementException();            Object[] elementData = ArrayList.this.elementData;            if (i >= elementData.length)                throw new ConcurrentModificationException();            cursor = i;            return (E) elementData[lastRet = i];        }        public void set(E e) {            if (lastRet < 0)                throw new IllegalStateException();            checkForComodification();            try {                ArrayList.this.set(lastRet, e);            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }        public void add(E e) {            checkForComodification();            try {                int i = cursor;                ArrayList.this.add(i, e);                cursor = i + 1;                lastRet = -1;                expectedModCount = modCount;            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }    }    //返回一个子列表    public List<E> subList(int fromIndex, int toIndex) {        //先判断范围        subListRangeCheck(fromIndex, toIndex, size);        return new SubList(this, 0, fromIndex, toIndex);    }    static void subListRangeCheck(int fromIndex, int toIndex, int size) {        if (fromIndex < 0)            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);        if (toIndex > size)            throw new IndexOutOfBoundsException("toIndex = " + toIndex);        if (fromIndex > toIndex)            throw new IllegalArgumentException("fromIndex(" + fromIndex +                                               ") > toIndex(" + toIndex + ")");    }    /**     * 由SubList的构造可知:SubList构造出来的List指向了父ArrayList,对SubList的所有操作都会反映到     * ArrayList上去,二者是一个共同体,不是独立出来的副本,这点很重要!!     *     */    private class SubList extends AbstractList<E> implements RandomAccess {        private final AbstractList<E> parent;        private final int parentOffset;        private final int offset;        int size;        SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) {            this.parent = parent;            this.parentOffset = fromIndex;            this.offset = offset + fromIndex;            this.size = toIndex - fromIndex;            this.modCount = ArrayList.this.modCount;        }        //可以看到所有的get、set操作都是在操作其父ArrayList,SubList只是记录了偏移量        public E set(int index, E e) {            rangeCheck(index);            checkForComodification();            E oldValue = ArrayList.this.elementData(offset + index);            ArrayList.this.elementData[offset + index] = e;            return oldValue;        }        public E get(int index) {            rangeCheck(index);            checkForComodification();            return ArrayList.this.elementData(offset + index);        }        public int size() {            checkForComodification();            return this.size;        }        public void add(int index, E e) {            rangeCheckForAdd(index);            checkForComodification();            parent.add(parentOffset + index, e);            this.modCount = parent.modCount;            this.size++;        }        public E remove(int index) {            rangeCheck(index);            checkForComodification();            E result = parent.remove(parentOffset + index);            this.modCount = parent.modCount;            this.size--;            return result;        }        protected void removeRange(int fromIndex, int toIndex) {            checkForComodification();            parent.removeRange(parentOffset + fromIndex,                               parentOffset + toIndex);            this.modCount = parent.modCount;            this.size -= toIndex - fromIndex;        }        public boolean addAll(Collection<? extends E> c) {            return addAll(this.size, c);        }        public boolean addAll(int index, Collection<? extends E> c) {            rangeCheckForAdd(index);            int cSize = c.size();            if (cSize==0)                return false;            checkForComodification();            parent.addAll(parentOffset + index, c);            this.modCount = parent.modCount;            this.size += cSize;            return true;        }        public Iterator<E> iterator() {            return listIterator();        }        public ListIterator<E> listIterator(final int index) {            checkForComodification();            rangeCheckForAdd(index);            final int offset = this.offset;            return new ListIterator<E>() {                int cursor = index;                int lastRet = -1;                int expectedModCount = ArrayList.this.modCount;                public boolean hasNext() {                    return cursor != SubList.this.size;                }                @SuppressWarnings("unchecked")                public E next() {                    checkForComodification();                    int i = cursor;                    if (i >= SubList.this.size)                        throw new NoSuchElementException();                    Object[] elementData = ArrayList.this.elementData;                    if (offset + i >= elementData.length)                        throw new ConcurrentModificationException();                    cursor = i + 1;                    return (E) elementData[offset + (lastRet = i)];                }                public boolean hasPrevious() {                    return cursor != 0;                }                @SuppressWarnings("unchecked")                public E previous() {                    checkForComodification();                    int i = cursor - 1;                    if (i < 0)                        throw new NoSuchElementException();                    Object[] elementData = ArrayList.this.elementData;                    if (offset + i >= elementData.length)                        throw new ConcurrentModificationException();                    cursor = i;                    return (E) elementData[offset + (lastRet = i)];                }                public int nextIndex() {                    return cursor;                }                public int previousIndex() {                    return cursor - 1;                }                public void remove() {                    if (lastRet < 0)                        throw new IllegalStateException();                    checkForComodification();                    try {                        SubList.this.remove(lastRet);                        cursor = lastRet;                        lastRet = -1;                        expectedModCount = ArrayList.this.modCount;                    } catch (IndexOutOfBoundsException ex) {                        throw new ConcurrentModificationException();                    }                }                public void set(E e) {                    if (lastRet < 0)                        throw new IllegalStateException();                    checkForComodification();                    try {                        ArrayList.this.set(offset + lastRet, e);                    } catch (IndexOutOfBoundsException ex) {                        throw new ConcurrentModificationException();                    }                }                public void add(E e) {                    checkForComodification();                    try {                        int i = cursor;                        SubList.this.add(i, e);                        cursor = i + 1;                        lastRet = -1;                        expectedModCount = ArrayList.this.modCount;                    } catch (IndexOutOfBoundsException ex) {                        throw new ConcurrentModificationException();                    }                }                final void checkForComodification() {                    if (expectedModCount != ArrayList.this.modCount)                        throw new ConcurrentModificationException();                }            };        }        public List<E> subList(int fromIndex, int toIndex) {            subListRangeCheck(fromIndex, toIndex, size);            return new SubList(this, offset, fromIndex, toIndex);        }        private void rangeCheck(int index) {            if (index < 0 || index >= this.size)                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));        }        private void rangeCheckForAdd(int index) {            if (index < 0 || index > this.size)                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));        }        private String outOfBoundsMsg(int index) {            return "Index: "+index+", Size: "+this.size;        }        private void checkForComodification() {            if (ArrayList.this.modCount != this.modCount)                throw new ConcurrentModificationException();        }    }}

由上可以得出以下结论:

  1. ArrayList使用数组进行数据保存,即(Object[] elementData),该对象修饰符为: private transient ,是不参与序列化的,序列化时,需调用提供的( private void writeObject(java.io.ObjectOutputStream s))方法,数组默认大小为10。
  2. 对数据进行Add操作时,ArrayList先进行了容量检查,如果不够保存当前对象,则进行扩容,扩容大小为当前容量的一半,即100扩容到150,再将旧数据复制过来,因此ArrayList有可能造成空间的浪费,在这一点上,ArrayList提供了一个trimToSize()方法,可以将数组长度置为size大小,可以压缩空间。
  3. 由于使用数组保存,在中间插入元素或删除元素时,调用了System.arraycopy方法,需要将插入点后面所有元素移位,该方法是一个native方法,直接内存复制,理论上效率还行,但也相比链表(LinkedList)效率还是不高。但是正因为使用了数组保存,get效率比较高,因此ArrayList适合于需要频繁读的情况。
  4. ArrayList的clone方法是浅复制。
  5. ArryList提供的subList(fromIndex,endIndex)方法返回的List和自身是同一个对象,对subList所有操作(增加、删除等)都会反映到ArrayList上,是一个共同体。
0 0
原创粉丝点击