源码-ArrayList

ArrayList


类结构图

在这里插入图片描述

成员变量

/**
 * Default initial capacity.默认初始容量
 */
private static final int DEFAULT_CAPACITY = 10;

/**
 * Shared empty array instance used for empty instances.
 *   共享空数组实例
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
 * Shared empty array instance used for default sized empty instances. We
 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
 * first element is added.
 *用于默认大小的空实例的共享空数组实例。我们将其与EMPTY_ELEMENTDATA区分开来,
  以了解添加第一个元素需要膨胀多少。
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer. Any
 * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
 * will be expanded to DEFAULT_CAPACITY when the first element is added.
   数组缓冲区,ArrayList的元素存储在其中。ArrayList的容量是这个数组缓冲区的长度。
   任何elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA的ArrayList将在添加第
   一个元素时容量扩展为DEFAULT_CAPACITY。
 */
transient Object[] elementData; // non-private to simplify nested class access

/**
 * The size of the ArrayList (the number of elements it contains).
 * 
 * @serial
 */
private int size;

构造方法

代码

构造方法1
/**
 * Constructs an empty list with the specified initial capacity.
 * 构造一个空的list带有指定的初始化容量
 * @param  initialCapacity  the initial capacity of the list
 * @throws IllegalArgumentException if the specified initial capacity
 *         is negative
 */
public ArrayList(int initialCapacity) {
    //初始化参数大于0
    if (initialCapacity > 0) {
        //创建相应大小的Obj数组
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        //如果初始化参数为0,也就是new ArrayList(0)而不是new ArrayList,两者还是有区别的
        //赋值为EMPTY_ELEMENTDATA
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}
构造方法2
 /**
 * Constructs an empty list with an initial capacity of ten.
   构造一个初始容量为10的空列表。
 */
public ArrayList() {
    //赋值为默认容量空list。其实第一次创建的时候也是空的list,会在第一次扩容改变,节省内存
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
构造方法3
/**
 * Constructs a list containing the elements of the specified
 * collection, in the order they are returned by the collection's
 * iterator.
 * 构造一个包含指定元素的列表集合,它们按集合的返回顺序返回迭代器。
 * @param c the collection whose elements are to be placed into this list
 * @throws NullPointerException if the specified collection is null
 */
public ArrayList(Collection<? extends E> c) {
    //将集合转换为数组
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        //判断返回的数组是否为obj数组,并对其进行处理
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        //如果数组为空,则直接赋值为EMPTY_ELEMENTDATA,也就是空数组
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

add(E e)方法

//Appends the specified element to the end of this list.添加指定元素到list尾部
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
/**
 * 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.、
 * 如果必要则增加此<tt>ArrayList</tt>实例的容量以确保它至少可以容纳元素的数量
   由最小容量参数指定。
 */
 //确保在容量内
private void ensureCapacityInternal(int minCapacity) {
    //如果是空list,则在添加元素的数量+1以及初始容量10之间取最大值,即为最小容量
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}
//确保明确容量
private void ensureExplicitCapacity(int minCapacity) {
    //数组改变次数
    modCount++;

    // overflow-conscious code
    //如果需要的最小容量大于当前容量
    if (minCapacity - elementData.length > 0)
        //扩容并传入最小容量
        grow(minCapacity);
}
//扩容
private void grow(int minCapacity) {
    // overflow-conscious code
    //扩容前的容量
    int oldCapacity = elementData.length;
    //扩容后的容量=扩容前+扩容前位运算右移一位
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //如果扩容后容量小于最小容量
    if (newCapacity - minCapacity < 0)
        //扩容后=最小容量
        newCapacity = minCapacity;
        //如果扩容后容量大于list的size
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        //扩容后=hugeCapacity
        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();
    //如果最小容量大于当前最大数组size则返回int最大值,否则将array最大size返回
    // MAX_ARRAY_SIZE = Integer.MAX_VALUE-8  8字节保存的是lenth字段
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

add(int index,E e)

public void add(int index, E element) {
    rangeCheckForAdd(index);
    //确保容量
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    //复制数组index+1到尾部,右移
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    //插入数据
    elementData[index] = element;
    //更新size
    size++;
}

trimToSize方法

/**
 * Trims the capacity of this <tt>ArrayList</tt> instance to be the
 * list's current size.  An application can use this operation to minimize
 * the storage of an <tt>ArrayList</tt> instance.
   将此<tt>ArrayList</tt>实例的容量修剪为列表的当前大小。应用程序可以使用此
   操作来最小化一个<tt>ArrayList</tt>实例的存储。
 */
public void trimToSize() {
    //list改变次数增加
    modCount++;
    //如果存入元素数量小于数组长度
    if (size < elementData.length) {
        elementData = (size == 0)
          ? EMPTY_ELEMENTDATA
          : Arrays.copyOf(elementData, size);
    }
}

ensureCapacity(int minCapacity)确保容量

public void ensureCapacity(int minCapacity) {
    //如果数组为DEFAULTCAPACITY_EMPTY_ELEMENTDATA则minExpand就为10否则为0
    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);
    }
}

addAll(Collection c)方法

/**
 * Appends all of the elements in the specified collection to the end of
 * this list, in the order that they are returned by the
 * specified collection's Iterator.  The behavior of this operation is
 * undefined if the specified collection is modified while the operation
 * is in progress.  (This implies that the behavior of this call is
 * undefined if the specified collection is this list, and this
 * list is nonempty.)
 *
 * @param c collection containing elements to be added to this list
 * @return <tt>true</tt> if this list changed as a result of the call
 * @throws NullPointerException if the specified collection is null
 */
public boolean addAll(Collection<? extends E> c) {
    //将传入集合转换为obj数组命名为a
    Object[] a = c.toArray();
    //得到numNew为a的长度
    int numNew = a.length;
    //确保容量操作
    ensureCapacityInternal(size + numNew);  // Increments modCount
    //复制数组elementData,并将a复制到从size到size+a.length的位置,也就是追加
    System.arraycopy(a, 0, elementData, size, numNew);
    //更新size的值
    size += numNew;
    return numNew != 0;
}

addAll(int index, Collection<? extends E> c)

/**
 * Inserts all of the elements in the specified collection into this
 * list, starting at the specified position.  Shifts the element
 * currently at that position (if any) and any subsequent elements to
 * the right (increases their indices).  The new elements will appear
 * in the list in the order that they are returned by the
 * specified collection's iterator.
 *
 将指定集合中的所有元素插入其中列表,从指定位置开始。变化的元素
 当前位于该位置(如果有的话)和任何后续元素到右派(提高他们的指数)。新元素将会出现
 方法返回它们的顺序指定集合的迭代器。
 * @param index index at which to insert the first element from the
 *              specified collection
 * @param c collection containing elements to be added to this list
 * @return <tt>true</tt> if this list changed as a result of the call
 * @throws IndexOutOfBoundsException {@inheritDoc}
 * @throws NullPointerException if the specified collection is null
 */
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)
        //将index之后的elementData数据复制到elementData的index+numNew作为起始位置的数组,也就               是移动了ele的位置
        System.arraycopy(elementData, index, elementData, index + numNew,
                         numMoved);
    //复制插入数组到指定位置
    System.arraycopy(a, 0, elementData, index, numNew);
    //更新size
    size += numNew;
    return numNew != 0;
}
//判断插入的位置index是否有效
private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

remove(int index)

/**
 * Removes the element at the specified position in this list.
 * Shifts any subsequent elements to the left (subtracts one from their
 * indices).从指标中减去1
 * 在list中的指定位置移除元素,将任何后续元素向左移动
 * @param index the index of the element to be removed
 * @return the element that was removed from the list
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E remove(int index) {
    //范围有效验证
    rangeCheck(index);

    modCount++;
    //得到需要移除的元素
    E oldValue = elementData(index);
    //需要移动的数据数量
    int numMoved = size - index - 1;
    if (numMoved > 0)
        //将index右侧数据向左移动,也就是将index+1以及后面数据复制到index位置上
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    //数据size减1
    elementData[--size] = null; // clear to let GC do its work
    //返回移除的元素
    return oldValue;
}

//范围验证
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

remove(Object o)

/**
 * 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).
 * 移除第一次出现的指定元素,如果不存在该元素,他是不改变的,移除的是index
   最小的元素
 * @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;
}

/*
 * 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
}

removeRange(int fromIndex, int toIndex)

/**
 * Removes from this list all of the elements whose index is between
 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
 * Shifts any succeeding elements to the left (reduces their index).
 * This call shortens the list by {@code (toIndex - fromIndex)} elements.
 * (If {@code toIndex==fromIndex}, this operation has no effect.)
 *
 * @throws IndexOutOfBoundsException if {@code fromIndex} or
 *         {@code toIndex} is out of range
 *         ({@code fromIndex < 0 ||
 *          fromIndex >= size() ||
 *          toIndex > size() ||
 *          toIndex < fromIndex})
 */
protected void removeRange(int fromIndex, int toIndex) {
    modCount++;
    int numMoved = size - toIndex;
    //将toIndex到size的元素复制到fromIndex起始位置
    System.arraycopy(elementData, toIndex, elementData, fromIndex,
                     numMoved);

    // clear to let GC do its work
    //清除留给gc
    int newSize = size - (toIndex-fromIndex);
    //将不需要的元素及位置赋值为null交给gc处理
    for (int i = newSize; i < size; i++) {
        elementData[i] = null;
    }
    //更新size
    size = newSize;
}

removeAll(Collection<?> c)

public boolean removeAll(Collection<?> c) {
    //确认不是null
    Objects.requireNonNull(c);
    //**retainAll(Collection<?> c)也会用到,批量删除**
    return batchRemove(c, false);
}

private boolean **batchRemove**(Collection<?> c, boolean complement) {
    //新建一个elementData赋值为当前elementData
    final Object[] elementData = this.elementData;
    **int r = 0, w = 0;**
    //修改=false
    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) {
            // clear to let GC do its work
            for (int i = w; i < size; i++)
                elementData[i] = null;
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

分析:
(1)、先分析

        for (; r < size; r++)
            if (c.contains(elementData[r]) == complement)
                elementData[w++] = elementData[r];

        这部分 因为 complement==false。所以,参数数组中不包含原数组指定位置的数据时
        就将原数组的r位置的数据覆盖掉w位置的数据,r位置的数据不变,并其w自增,r自增。
        否则,r自增,w不自增

        这步处理出来的数据很重要,一定要理解到,下面举个例子:

            原数组:     123456789   ;     参数数组:  abc358f                                                                  

            数组位置     012345678

循环次数    r   w  if值   elementData[w++]=elementData[r]           原数组值     替换位
1          0   0  true     elementData[0]=elementData[0]         123456789   123456789
2          1   1  true     elementData[1]=elementData[1]         123456789   123456789
3          2   2  false                                                                 123456789  
4          3   2  true     elementData[2]=elementData[3]         124456789   123456789
5          4   3  false                                                                 124456789
6          5   3  true     elementData[3]=elementData[5]         124656789   124456789
7          6   4  true     elementData[4]=elementData[6]         124676789   124656789 
8          7   5  false                                                                 124676789 
9          8   5  true     elementData[5]=elementData[8]         124679789   124676789 

            9   6

这步的作用:把需要移除的数据都替换掉,不需要移除的数据前移。(这步的处理尤为重要!)
(2)、再分析

                        if (w != size) {
                            // clear to let GC do its work
                            for (int i = w; i < size; i++)
                                elementData[i] = null;
                            modCount += size - w;
                            size = w;
                            modified = true;
                        }

        跟着上面的例子,w==6,从原数组124679789的 下标==6开始,将原数组大于下标6以后的数置null
        modCount 修改的次数+3,原数组的长度修改为6。

reatainAll(Collection<?> c) 交集

public boolean retainAll(Collection<?> c) {
    Objects.requireNonNull(c);
    return batchRemove(c, true);
}

indexOf(Object o)查找单个元素

/**
 * Returns the index of the first occurrence/出现 of the specified element
 * in this list, or -1 if this list does not contain the element.
 * More formally, returns the lowest index <tt>i</tt> such that
 * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
 * or -1 if there is no such index.
   返回第一次出现的指定元素,不存在返回-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;
}

contains(Object o)是否存在此元素

/**
 * Returns <tt>true</tt> if this list contains the specified element.
 * More formally, returns <tt>true</tt> if and only if this list contains
 * at least one element <tt>e</tt> such that
 * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
 *
 * @param o element whose presence in this list is to be tested
 * @return <tt>true</tt> if this list contains the specified element
 */
public boolean contains(Object o) {
    return indexOf(o) >= 0;
}

lastIndexOf(Object o)返回最后出现的元素下标

/**
 * Returns the index of the last occurrence of the specified element
 * in this list, or -1 if this list does not contain the element.
 * More formally, returns the highest index <tt>i</tt> such that
 * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
 * or -1 if there is no such index.
 */
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(int index)获取指定元素

 /**
 * Returns the element at the specified position in this list.
 *
 * @param  index index of the element to return
 * @return the element at the specified position in this list
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

set(int index, E element)设置指定元素

/**
 * Replaces the element at the specified position in this list with
 * the specified element.
 *
 * @param index index of the element to replace
 * @param element element to be stored at the specified position
 * @return the element previously at the specified position
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E set(int index, E element) {
    rangeCheck(index);

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

toArray()转换为数组

/**
 * Returns an array containing all of the elements in this list
 * in proper/适当的 sequence/顺序 (from first to last element).
 *
 * <p>The returned array will be "safe" in that no references to it are
 * maintained by this list.  (In other words, this method must allocate
 * a new array).  The caller is thus free to modify the returned array.
 *
 * <p>This method acts as bridge between array-based and collection-based
 * APIs.
 *
 * @return an array containing all of the elements in this list in
 *         proper sequence
 */
public Object[] toArray() {
    //调用Arrays工具类返回obj数组
    return Arrays.copyOf(elementData, size);
}

toArray(T[] a)

/**
 * Returns an array containing all of the elements in this list in proper
 * sequence (from first to last element); the runtime type of the returned
 * array is that of the specified array.  If the list fits in the
 * specified array, it is returned therein.  Otherwise, a new array is
 * allocated with the runtime type of the specified array and the size of
 * this list.
 *
 * <p>If the list fits in the specified array with room to spare
 * (i.e., the array has more elements than the list), the element in
 * the array immediately following the end of the collection is set to
 * <tt>null</tt>.  (This is useful in determining the length of the
 * list <i>only</i> if the caller knows that the list does not contain
 * any null elements.)
 *
 * @param a the array into which the elements of the list are to
 *          be stored, if it is big enough; otherwise, a new array of the
 *          same runtime type is allocated for this purpose.
 * @return an array containing the elements of the list
 * @throws ArrayStoreException if the runtime type of the specified array
 *         is not a supertype of the runtime type of every element in
 *         this list
 * @throws NullPointerException if the specified array is null
 */
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        //如果传入的数组小于size,则直接复制新数组返回
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    //复制elementData到a中,也就是:
        //原数组:elemenetData
        //原数组起始下标:0
        //目的数组:a
        //目的数组起始下标:0
        //复制的个数:size
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

https://blog.csdn.net/w605283073/article/details/92095862 代码演示,将最后一个元素设置为null

hashCode()/AbstractList中的hashCode

public int hashCode() {
    int hashCode = 1;
    for (E e : this)
        hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    return hashCode;
}

equals(Object o)/AbstractList

/**
 * Compares the specified object with this list for equality.  Returns
 * {@code true} if and only if the specified object is also a list, both
 * lists have the same size, and all corresponding pairs of elements in
 * the two lists are <i>equal</i>.  (Two elements {@code e1} and
 * {@code e2} are <i>equal</i> if {@code (e1==null ? e2==null :
 * e1.equals(e2))}.)  In other words, two lists are defined to be
 * equal if they contain the same elements in the same order.<p>
 *
 * This implementation first checks if the specified object is this
 * list. If so, it returns {@code true}; if not, it checks if the
 * specified object is a list. If not, it returns {@code false}; if so,
 * it iterates over both lists, comparing corresponding pairs of elements.
 * If any comparison returns {@code false}, this method returns
 * {@code false}.  If either iterator runs out of elements before the
 * other it returns {@code false} (as the lists are of unequal length);
 * otherwise it returns {@code true} when the iterations complete.
 *
 * @param o the object to be compared for equality with this list
 * @return {@code true} if the specified object is equal to this list
 */
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof List))
        return false;

    //获取当前list迭代器
    ListIterator<E> e1 = listIterator();
    //获取传入参数迭代器
    ListIterator<?> e2 = ((List<?>) o).listIterator();
    //两个迭代器都有下一个参数
    while (e1.hasNext() && e2.hasNext()) {
        E o1 = e1.next();
        Object o2 = e2.next();
        //如果存在连个元素不相等返回false,否则继续遍历
        if (!(o1==null ? o2==null : o1.equals(o2)))
            return false;
    }
    //其中一个或者两个都没有下一个元素,判断其中是否还有元素
    return !(e1.hasNext() || e2.hasNext());
}

public ListIterator<E> listIterator() {
    return listIterator(0);
}

clear()清空数组

/**
 * Removes all of the elements from this list.  The list will
 * be empty after this call returns.
 */
public void clear() {
    modCount++;
    //赋值为null,交给gc处理
    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

writeObject(java.io.ObjectOutputStream s)序列化数组

 /**
 * 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;
    **[//https://juejin.im/entry/5bf622436fb9a04a0b21cbe7(serializable原理)][1]**
    //序列化非静态属性,非transient属性
    s.defaultWriteObject();

    // Write out size as capacity for behavioural compatibility with clone()
    //写入size主要与克隆方法兼容
    **//https://www.zhihu.com/question/41512382**
    s.writeInt(size);
    //将数组中数据写出
    // Write out all elements in the proper order.
    for (int i=0; i<size; i++) {
        s.writeObject(elementData[i]);
    }
    //序列化期间如果modCount有改变则抛出异常
    //直接序列化浪费空间使用遍历序列化
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}

serializable原理
写入size与克隆方法兼容

readObject(java.io.ObjectInputStream s)反序列化

 /**
 * 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 {
    elementData = EMPTY_ELEMENTDATA;

    // Read in size, and any hidden stuff
    //读取非静态属性非transient属性
    s.defaultReadObject();

    // Read in capacity
    //读取容量可以忽略
    s.readInt(); // ignored

    if (size > 0) {
        // be like clone(), allocate array based upon size not capacity
        //确保容量范围
        //优化后,扩容从0开始读取size后扩容
        ensureCapacityInternal(size);
        //读取属性并反序列化
        Object[] a = elementData;
        // Read in all elements in the proper order.
        for (int i=0; i<size; i++) {
            a[i] = s.readObject();
        }
    }
}

clone()克隆

/** 浅拷贝
 * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
 * elements themselves are not copied.)
 *
 * @return a clone of this <tt>ArrayList</tt> instance
 */
public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        //拷贝新数组
        v.elementData = Arrays.copyOf(elementData, size);
        //设置modCount=0
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

subList(int fromIndex, int toIndex)创建子数组

/**
 * Returns a view of the portion of this list between the specified
 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.  (If
 * {@code fromIndex} and {@code toIndex} are equal, the returned list is
 * empty.)  
   包前不包后,如果相等则返回空list
   The returned list is backed by this list, so non-structural
 * changes in the returned list are reflected in this list, and vice-versa.
 * The returned list supports all of the optional list operations.
 *
 * <p>This method eliminates the need for explicit range operations (of
 * the sort that commonly exist for arrays).  Any operation that expects
 * a list can be used as a range operation by passing a subList view
 * instead of a whole list.  For example, the following idiom
 * removes a range of elements from a list:
 * <pre>
 *      list.subList(from, to).clear();
 * </pre>
 * Similar idioms may be constructed for {@link #indexOf(Object)} and
 * {@link #lastIndexOf(Object)}, and all of the algorithms in the
 * {@link Collections} class can be applied to a subList.
 *
 * <p>The semantics of the list returned by this method become undefined if
 * the backing list (i.e., this list) is <i>structurally modified</i> in
 * any way other than via the returned list.  (Structural modifications are
 * those that change the size of this list, or otherwise perturb it in such
 * a fashion that iterations in progress may yield incorrect results.)
 *
 * @throws IndexOutOfBoundsException {@inheritDoc}
 * @throws IllegalArgumentException {@inheritDoc}
 */
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;
    }
}

iterator()获取迭代器

/**
 * Returns an iterator over the elements in this list in proper sequence.
 *
 * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
 *
 * @return an iterator over the elements in this list in proper sequence
 */
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; //数组修改次数

    public boolean hasNext() {
        //下一个元素指针不是size,说明还有下一个元素
        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;
        //返回当前元素,并将lastRet赋值为i
        return (E) elementData[lastRet = i];
    }

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

        try {
            //删除当前元素,也就是lastRet指向的元素
            ArrayList.this.remove(lastRet);
            //cursor指针左移,也就是lastRet
            cursor = lastRet;
            //标记当前元素被删除
            lastRet = -1;
            //修改数变化
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
        //要求action非空
        Objects.requireNonNull(consumer);
        final int size = ArrayList.this.size;
        int i = cursor;
        //如果当前指针大于或者等于size,迭代完毕或者出现异常
        if (i >= size) {
            return;
        }
        final Object[] elementData = ArrayList.this.elementData;
        //如果判断i此时大于数组长度,则抛出修改异常
        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();
    }
}

listIterator(int index)/listIterator()获取list迭代器

/**
 * Returns a list iterator over the elements in this list (in proper
 * sequence), starting at the specified position in the list.
 * The specified index indicates the first element that would be
 * returned by an initial call to {@link ListIterator#next next}.
 * An initial call to {@link ListIterator#previous previous} would
 * return the element with the specified index minus one.
 *
 * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
 *
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public ListIterator<E> listIterator(int index) {
    if (index < 0 || index > size)
        throw new IndexOutOfBoundsException("Index: "+index);
    return new ListItr(index);
}

/**
 * Returns a list iterator over the elements in this list (in proper
 * sequence).
 *
 * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
 *
 * @see #listIterator(int)
 */
public ListIterator<E> listIterator() {
    return new ListItr(0);
}
//list迭代器继承自Itr并实现ListInteractor
//在Itr基础之上增加一些功能
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();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值