Java源码分析之ArrayList(下)

来源:互联网 发布:php array diff key 编辑:程序博客网 时间:2024/06/06 16:31
package java.util;import java.util.function.Consumer;import java.util.function.Predicate;import java.util.function.UnaryOperator;public class ArrayList<E> extends AbstractList<E> implements List<E>,        RandomAccess, Cloneable, java.io.Serializable {    //Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的    private static final long serialVersionUID = 8683452581122892189L;    private static final int DEFAULT_CAPACITY = 10;//默认容量    //空的对象数组(用于new ArrayList(0)的初始化)    private static final Object[] EMPTY_ELEMENTDATA = {};    //用于new ArrayList()的初始化    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};    transient Object[] elementData;//真正保存数据的数组 不可序列化    private int size;//ArrayList的实际元素数量    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);        }    }    public ArrayList() {//无参构造        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;    }    public ArrayList(Collection<? extends E> c) {//构造一个包含指定c元素的列表        elementData = c.toArray();        if ((size = elementData.length) != 0) {            //检查类型            if (elementData.getClass() != Object[].class)                elementData = Arrays.copyOf(elementData, size, Object[].class);        } else {            this.elementData = EMPTY_ELEMENTDATA;        }    }    public void trimToSize() {//调整ArrayList的实际容量为size        modCount++;//modCount记录修改次数+1        if (size < elementData.length) {            elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(                    elementData, size);        }    }    public void ensureCapacity(int minCapacity) {        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)? 0            : DEFAULT_CAPACITY;        if (minCapacity > minExpand) {            ensureExplicitCapacity(minCapacity);        }    }    private void ensureCapacityInternal(int minCapacity) {        //如果实际存储数组是空数组 则最小需要容量就是默认容量        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);        }        ensureExplicitCapacity(minCapacity);    }    private void ensureExplicitCapacity(int minCapacity) {        modCount++;        //如果数组(elementData)的长度小于最小需要的容量(minCapacity)就扩容        if (minCapacity - elementData.length > 0)            grow(minCapacity);    }    /*    这个-8是为了减少出错的几率,避免一些机器内存溢出,最大长度依然是Integer.MAX_VALUE    并不是Integer.MAX_VALUE-8(通过hugeCapacity()方法调整)    */    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;    private void grow(int minCapacity) {        int oldCapacity = elementData.length;        //扩容为原来的1.5倍        int newCapacity = oldCapacity + (oldCapacity >> 1);        //如果扩容1.5倍仍小于最小需要容量(针对addAll方法),就直接扩容为最小需要容量        if (newCapacity - minCapacity < 0)            newCapacity = minCapacity;        //若超出MAX_ARRAY_SIZE,调用hugeCapacity调整        if (newCapacity - MAX_ARRAY_SIZE > 0)            newCapacity = hugeCapacity(minCapacity);        //复制元素        elementData = Arrays.copyOf(elementData, newCapacity);    }    private static int hugeCapacity(int minCapacity) {        if (minCapacity < 0)            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;    }    public int indexOf(Object o) {//返回o第一次出现的索引,没有就返回-1        if (o == null) {//判断o是否为null,避免出现o.equals空指针异常            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;    }    public int lastIndexOf(Object o) {//返回o最后一次出现的索引,没有就返回-1        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 {            ArrayList<?> v = (ArrayList<?>) super.clone();            v.elementData = Arrays.copyOf(elementData, size);            v.modCount = 0;            return v;        } catch (CloneNotSupportedException e) {            throw new InternalError(e);        }    }    public Object[] toArray() {//集合转换为数组        return Arrays.copyOf(elementData, size);    }    @SuppressWarnings("unchecked")    public <T> T[] toArray(T[] a) {//通过泛型约束返回指定类型的数组        if (a.length < size)            return (T[]) Arrays.copyOf(elementData, size, a.getClass());        /*        elementData:源数组 0:源数组要复制的起始位置        a:目的数组 0:目的数组要复制的起始位置        size:复制的长度        */        System.arraycopy(elementData, 0, a, 0, size);        if (a.length > size)            a[size] = null;        return a;    }    @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) {//用element替代指定位置上的元素        rangeCheck(index);        E oldValue = elementData(index);        elementData[index] = element;        return oldValue;//返回之前位于index上的元素    }    public boolean add(E e) {//在列表尾部添加指定元素        ensureCapacityInternal(size + 1);        elementData[size++] = e;        return true;    }    //把element添加到指定位置,当前元素和后续元素(如果有的话)向后移动    public void add(int index, E element) {        rangeCheckForAdd(index);        ensureCapacityInternal(size + 1);        //整体后移        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)//numMoved=0,移除的是最后一个元素            System.arraycopy(elementData, index + 1, elementData, index,                    numMoved);        elementData[--size] = null;        return oldValue;//返回从列表中移除的元素    }    //如果集合中有o,则删除第一次出现的并返回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;    }    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;    }    public void clear() {//移除列表所有元素        modCount++;        for (int i = 0; i < size; i++)            elementData[i] = null;        size = 0;    }    public boolean addAll(Collection<? extends E> c) {//添加集合c中的所有元素到列表尾部        Object[] a = c.toArray();        int numNew = a.length;        ensureCapacityInternal(size + numNew);        System.arraycopy(a, 0, elementData, size, numNew);        size += numNew;        return numNew != 0;    }    //从指定的位置开始,移动c中的所有元素到列表中,当前元素和后续元素(如果有的话)向右移动    public boolean addAll(int index, Collection<? extends E> c) {        rangeCheckForAdd(index);        Object[] a = c.toArray();        int numNew = a.length;        ensureCapacityInternal(size + numNew);        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;    }    //移除列表中索引在fromIndex(包括)和toIndex(不包括)之间的所有元素    protected void removeRange(int fromIndex, int toIndex) {        modCount++;        int numMoved = size - toIndex;        System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved);        int newSize = size - (toIndex - fromIndex);        for (int i = newSize; i < size; i++) {            elementData[i] = null;        }        size = newSize;    }    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) {        //传入的参数不为null,返回参数本身,为null,抛出一个空指针异常        Objects.requireNonNull(c);        return batchRemove(c, false);    }    public boolean retainAll(Collection<?> c) {        Objects.requireNonNull(c);        return batchRemove(c, true);    }    //beautiful code!    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 {            //发生了异常,直接把r后面的复制到w后面            if (r != size) {                System.arraycopy(elementData, r, elementData, w, size - r);                w += size - r;            }            if (w != size) {                //清除多余元素 更好的GC                for (int i = w; i < size; i++)                    elementData[i] = null;                modCount += size - w;                size = w;                modified = true;            }        }        return modified;    }    private void writeObject(java.io.ObjectOutputStream s)            throws java.io.IOException {        int expectedModCount = modCount;        s.defaultWriteObject();        s.writeInt(size);        for (int i = 0; i < size; i++) {            s.writeObject(elementData[i]);        }        if (modCount != expectedModCount) {            throw new ConcurrentModificationException();        }    }    private void readObject(java.io.ObjectInputStream s)            throws java.io.IOException, ClassNotFoundException {        elementData = EMPTY_ELEMENTDATA;        s.defaultReadObject();        s.readInt();        if (size > 0) {            ensureCapacityInternal(size);            Object[] a = elementData;            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();    }    private class Itr implements Iterator<E> {        int cursor;        int lastRet = -1;        int expectedModCount = modCount;        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++]);            }            cursor = i;            lastRet = i - 1;            checkForComodification();        }        final void checkForComodification() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();        }    }    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 + ")");    }    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;        }        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)];                }                @SuppressWarnings("unchecked")                public void forEachRemaining(Consumer<? super E> consumer) {                    Objects.requireNonNull(consumer);                    final int size = SubList.this.size;                    int i = cursor;                    if (i >= size) {                        return;                    }                    final Object[] elementData = ArrayList.this.elementData;                    if (offset + i >= elementData.length) {                        throw new ConcurrentModificationException();                    }                    while (i != size && modCount == expectedModCount) {                        consumer.accept((E) elementData[offset + (i++)]);                    }                    lastRet = cursor = i;                    checkForComodification();                }                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();        }        public Spliterator<E> spliterator() {            checkForComodification();            return new ArrayListSpliterator<E>(ArrayList.this, offset, offset                    + this.size, this.modCount);        }    }    @Override    public void forEach(Consumer<? super E> action) {        Objects.requireNonNull(action);        final int expectedModCount = modCount;        @SuppressWarnings("unchecked")        final E[] elementData = (E[]) this.elementData;        final int size = this.size;        for (int i = 0; modCount == expectedModCount && i < size; i++) {            action.accept(elementData[i]);        }        if (modCount != expectedModCount) {            throw new ConcurrentModificationException();        }    }    @Override    public Spliterator<E> spliterator() {        return new ArrayListSpliterator<>(this, 0, -1, 0);    }    static final class ArrayListSpliterator<E> implements Spliterator<E> {        private final ArrayList<E> list;        private int index;        private int fence;        private int expectedModCount;        /** Create new spliterator covering the given range */        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,                int expectedModCount) {            this.list = list;            this.index = origin;            this.fence = fence;            this.expectedModCount = expectedModCount;        }        private int getFence() {            int hi;            ArrayList<E> lst;            if ((hi = fence) < 0) {                if ((lst = list) == null)                    hi = fence = 0;                else {                    expectedModCount = lst.modCount;                    hi = fence = lst.size;                }            }            return hi;        }        public ArrayListSpliterator<E> trySplit() {            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;            return (lo >= mid) ? null : new ArrayListSpliterator<E>(list, lo,                    index = mid, expectedModCount);        }        public boolean tryAdvance(Consumer<? super E> action) {            if (action == null)                throw new NullPointerException();            int hi = getFence(), i = index;            if (i < hi) {                index = i + 1;                @SuppressWarnings("unchecked")                E e = (E) list.elementData[i];                action.accept(e);                if (list.modCount != expectedModCount)                    throw new ConcurrentModificationException();                return true;            }            return false;        }        public void forEachRemaining(Consumer<? super E> action) {            int i, hi, mc;            ArrayList<E> lst;            Object[] a;            if (action == null)                throw new NullPointerException();            if ((lst = list) != null && (a = lst.elementData) != null) {                if ((hi = fence) < 0) {                    mc = lst.modCount;                    hi = lst.size;                } else                    mc = expectedModCount;                if ((i = index) >= 0 && (index = hi) <= a.length) {                    for (; i < hi; ++i) {                        @SuppressWarnings("unchecked")                        E e = (E) a[i];                        action.accept(e);                    }                    if (lst.modCount == mc)                        return;                }            }            throw new ConcurrentModificationException();        }        public long estimateSize() {            return (long) (getFence() - index);        }        public int characteristics() {            return Spliterator.ORDERED | Spliterator.SIZED                    | Spliterator.SUBSIZED;        }    }    @Override    public boolean removeIf(Predicate<? super E> filter) {        Objects.requireNonNull(filter);        int removeCount = 0;        final BitSet removeSet = new BitSet(size);        final int expectedModCount = modCount;        final int size = this.size;        for (int i = 0; modCount == expectedModCount && i < size; i++) {            @SuppressWarnings("unchecked")            final E element = (E) elementData[i];            if (filter.test(element)) {                removeSet.set(i);                removeCount++;            }        }        if (modCount != expectedModCount) {            throw new ConcurrentModificationException();        }        final boolean anyToRemove = removeCount > 0;        if (anyToRemove) {            final int newSize = size - removeCount;            for (int i = 0, j = 0; (i < size) && (j < newSize); i++, j++) {                i = removeSet.nextClearBit(i);                elementData[j] = elementData[i];            }            for (int k = newSize; k < size; k++) {                elementData[k] = null;            }            this.size = newSize;            if (modCount != expectedModCount) {                throw new ConcurrentModificationException();            }            modCount++;        }        return anyToRemove;    }    @Override    @SuppressWarnings("unchecked")    public void replaceAll(UnaryOperator<E> operator) {        Objects.requireNonNull(operator);        final int expectedModCount = modCount;        final int size = this.size;        for (int i = 0; modCount == expectedModCount && i < size; i++) {            elementData[i] = operator.apply((E) elementData[i]);        }        if (modCount != expectedModCount) {            throw new ConcurrentModificationException();        }        modCount++;    }    @Override    @SuppressWarnings("unchecked")    public void sort(Comparator<? super E> c) {        final int expectedModCount = modCount;        Arrays.sort((E[]) elementData, 0, size, c);        if (modCount != expectedModCount) {            throw new ConcurrentModificationException();        }        modCount++;    }}