ArrayList源码分析

源码分析

属性分析

private static final long serialVersionUID = 8683452581122892189L;

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

/**
 * Shared empty array instance used for empty instances.
   用于空实例的共享空数组实例。
 */
private static final Object[] 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 == EMPTY_ELEMENTDATA will be expanded to
 * DEFAULT_CAPACITY when the first element is added.
   存储ArrayList元素的数组缓冲区。 * ArrayList的容量是此数组缓冲区的长度。添加第一个元素时,任何具有       elementData == 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).
 *  ArrayList的大小(它包含的元素数)。
 * @serial
 */
private int size; // 默认值为0

 /**
     * The number of times this list has been <i>structurally modified</i>.
     * Structural modifications are those that change the size of the
     * list, or otherwise perturb it in such a fashion that iterations in
     * progress may yield incorrect results.
     *
     * <p>This field is used by the iterator and list iterator implementation
     * returned by the {@code iterator} and {@code listIterator} methods.
     * If the value of this field changes unexpectedly, the iterator (or list
     * iterator) will throw a {@code ConcurrentModificationException} in
     * response to the {@code next}, {@code remove}, {@code previous},
     * {@code set} or {@code add} operations.  This provides
     * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
     * the face of concurrent modification during iteration.
     *
     * <p><b>Use of this field by subclasses is optional.</b> If a subclass
     * wishes to provide fail-fast iterators (and list iterators), then it
     * merely has to increment this field in its {@code add(int, E)} and
     * {@code remove(int)} methods (and any other methods that it overrides
     * that result in structural modifications to the list).  A single call to
     * {@code add(int, E)} or {@code remove(int)} must add no more than
     * one to this field, or the iterators (and list iterators) will throw
     * bogus {@code ConcurrentModificationExceptions}.  If an implementation
     * does not wish to provide fail-fast iterators, this field may be
     * ignored.
       此列表被<i>结构修改</ i>的次数。 *结构性修改是指更改*列表大小,或以其他方式干扰列表*进行迭代可能会产生错误结果的方式。 * * <p> {@ code iterator}和{@code listIterator}方法返回的迭代器和列表迭代器实现使用此字段。 *如果此字段的值意外更改,则迭代器(或列表*迭代器)将在对{@code next},{@ code remove},{@ code previous},*的响应中抛出{@code ConcurrentModificationException} {@code set}或{@code add}操作。这提供了* i-fail-fast </ i>行为,而不是*在迭代过程中面对并发修改时具有不确定性。 * * <p> <b>子类对该字段的使用是可选的。</ b>如果子类*希望提供快速失败的迭代器(和列表迭代器),则它仅需要在其{ @code add(int,E)}和* {@code remove(int)}方法(以及它覆盖的所有其他方法*会导致对该列表进行结构修改)。一次调用* {@code add(int,E)}或{@code remove(int)}不得在此字段中添加*个以上的字符,否则迭代器(和列表迭代器)将抛出假冒的{@code ConcurrentModificationExceptions}。如果实现不希望提供快速失败的迭代器,则可以忽略此字段。
     */
    protected transient int modCount = 0; //保证迭代当中集合不被修改,修改则会抛出ConcurrentModificationException,提供快速失败的迭代器,则可以忽略此字段。

 /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     要分配的最大数组大小。 *一些虚拟机在数组中保留一些标题字。 *尝试分配更大的阵列可能会导致* OutOfMemoryError:请求的阵列大小超出VM限制
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

方法分析

add
 /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        // 确保内部容量可以存下当前数据,如果初始化时无参构造器,则第一次调用add方法再对底层数组初始化。
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    
// 第一次初始化获取 DEFAULT_CAPACITY 和 传入值 最大值初始化底层数组
private void ensureCapacityInternal(int minCapacity) {
    // 第一次进入 minCapacity =(size + 1),size为成员变量默认为0,所以第一次为1
    // 调用的无参构造器 elementData 默认就是 EMPTY_ELEMENTDATA
    if (elementData == EMPTY_ELEMENTDATA) {
        // DEFAULT_CAPACITY 默认值为10 minCapacity = 1
        // 第一次初始化会进入这个方法,取最大值初始化
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    // minCapacity 存取的第几个数据 (第一次例外)
    ensureExplicitCapacity(minCapacity);
}

// 决定是否需要扩容
private void ensureExplicitCapacity(int minCapacity) {
    // minCapacity = 10
    // modCount 记录集合被修改的次数,快速响应一个迭代出错。 意思为迭代的时候,有其他地方动了集合的数   
    // 据。快速的响应抛出异常
        modCount++;

    // overflow-conscious code 有溢出意识的代码
    //(第一次为 10,后面为需要存入数据的索引(size + 1)数组长度从1开始,所以集合索引需要加一判断,正好够存入这个数据,则不扩容)
    // 如果当前需要存入的第几个数据 大于 集合的长度
        if (minCapacity - elementData.length > 0)
            // 增长,扩容内部数组
            grow(minCapacity);
}

 /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     增加容量,以确保它至少可以容纳最小容量参数指定的*个元素。 * * @param minCapacity所需的最小容量
     */
private void grow(int minCapacity) {
    // overflow-conscious code
    // 得到老数组的长度
    int oldCapacity = elementData.length;
    // 计算新 数组的长度 = 老数组 * 1.5  内存溢出后为负数
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 如果新数组 小于 当前需要存入的第几个数据 (一些特殊的数值才会进入,0*1.5 = 0 1*1.5 = 1.5 )
    if (newCapacity - minCapacity < 0)
        // 只有当存不下这个长度的数据才会进来 内存溢出也会进入
        newCapacity = minCapacity;
    // 如果新数组的长度已经 大于 Integer.MAX_VALUE - 8 数组已经很庞大了
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        // 决定新数组的大小 
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    // 底层数组的 复制返回新数组 复制长度为 Math.min(elementData.length, newCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}
// 决定数组大小
 private static int hugeCapacity(int minCapacity) {
     if (minCapacity < 0) // overflow 已经内存溢出了过了
         throw new OutOfMemoryError();
     // 当前需要存入的第几个数据 大于 Integer.MAX_VALUE - 8 成立 ? Integer.MAX_VALUE 不成立 Integer.MAX_VALUE - 8
     return (minCapacity > MAX_ARRAY_SIZE) ?
         Integer.MAX_VALUE :
     MAX_ARRAY_SIZE;
}

get
/**
 * 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}
   返回此列表中指定位置的元素。 * * @要返回的元素的索引索引* @返回此列表中指定位置的元素* @throws IndexOutOfBoundsException {@inheritDoc} 
 */
public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

/**
 * Checks if the given index is in range.  If not, throws an appropriate
 * runtime exception.  This method does *not* check if the index is
 * negative: It is always used immediately prior to an array access,
 * which throws an ArrayIndexOutOfBoundsException if index is negative.
   如果给定的索引在范围内,则返回。如果不是,则抛出适当的*运行时异常。此方法不检查索引是否为负数:始终在访问数组之前立即使用它,如果索引为负数,则抛出ArrayIndexOutOfBoundsException。
*/
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
remove
/**
 * Removes the element at the specified position in this list.
 * Shifts any subsequent elements to the left (subtracts one from their
 * indices).
 *
 * @param index the index of the element to be removed
 * @return the element that was removed from the list
 * @throws IndexOutOfBoundsException {@inheritDoc}
 / ** *删除此列表中指定位置的元素。 *将所有后续元素向左移动(从它们的*索引中减去一个)。 * * @param index要删除的元素的索引* @返回从列表中删除的元素* @throws IndexOutOfBoundsException {@inheritDoc} * /
 */
// 根据下标删除元素
public E remove(int index) {
    // 检查下标是否越界 不检查索引是否为负数
    rangeCheck(index);
    // 操作次数加1
    modCount++;
    // 拿到需要删除的值返回
    E oldValue = elementData(index);
    // 需要复制的数组长度
    int numMoved = size - index - 1;
    // 如果=0 说明是最后一个元素直接删除即可,不是最后一个需要进行一个复制操作
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    // 最后一个赋值为null,删除后数据全部往左推
    elementData[--size] = null; // clear to let GC do its work
    // 返回删除的值
    return oldValue;
}


/**
     * Removes the first occurrence of the specified element from this list,
     * if it is present.  If the list does not contain the element, it is
     * unchanged.  More formally, removes the element with the lowest index
     * <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
     * (if such an element exists).  Returns <tt>true</tt> if this list
     * contained the specified element (or equivalently, if this list
     * changed as a result of the call).
     *
     * @param o element to be removed from this list, if present
     * @return <tt>true</tt> if this list contained the specified element
      ** *从此列表中删除第一次出现的指定元素,如果存在*。如果列表不包含元素,则*不变。更正式地,删除具有最低索引* <tt> i </ tt>的元素,使得* <tt>(o == null?get(i)== null:o.equals(get(i)))< / tt> *(如果存在这样的元素)。如果此列表*包含指定的元素,则返回<tt> true </ tt>(或者等效地,如果此列表*由于调用而更改),则返回<tt> true </ tt>。 * * @param o要从此列表中删除的元素(如果存在)* @return <tt> true </ tt>如果此列表包含指定的元素* /
     */
    // 根据对象删除元素,返回此集合是否包含此传入的元素
    public boolean remove(Object o) {
        // 判断对象为不为null
        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++)
                // 底层条用equals进行比较,如果是对象可以重写equals方法来达到需要的效果
                if (o.equals(elementData[index])) {
                    // 传入索引删除
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
    // 没有重写的equals方法
    public boolean equals(Object obj) {
        return (this == obj);
    }
    // 快速删除方法
    /*
     * Private remove method that skips bounds checking and does not
     * return the value removed.
       专用的remove方法,跳过边界检查,并且不返回删除的值
     */
    private void fastRemove(int index) {
        // 操作数加1
        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
    }
contains
/**
 * 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
 / ** *如果此列表包含指定的元素,则返回<tt> true </ tt>。 *更正式地讲,当且仅当此列表包含*至少一个元素<tt> e </ tt>使得* <tt>(o == null?e == null: o.equals(e))</ tt>。 * * @param o要在此列表中进行测试的元素* @return <tt> true </ tt>如果此列表包含指定的元素* /
 */
// 判断此集合是否包含元素
public boolean contains(Object o) {
    // 如果返回的下标大于等于0 说明此列表中包含此元素
    return indexOf(o) >= 0;
}

    
indexOf
    /**
     * 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。 *更正式地,返回最低索引<tt> i </ tt>以便* <tt>(o == null?get(i)== null:o.equals(get(i)))</ tt> ,*或-1(如果没有这样的索引)。
     */
    public int indexOf(Object o) {
        // 判断是否为null
        if (o == null) {
            // 循环遍历 返回首次出现的下标
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
             // 循环遍历 返回首次出现的下标,调用equals进行比较
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    // 返回首次出现的下标
                    return i;
        }
        // 没有找到返回 -1 
        return -1;
    }
size
/**
 * Returns the number of elements in this list.
 *
 * @return the number of elements in this list
 */
public int size() {
    // 直接返回内部属性值
    return size;
}
clear
/**
 * Removes all of the elements from this list.  The list will
 * be empty after this call returns.
   / ** *从此列表中删除所有元素。该调用返回后,列表将*为空。 * /
 */
public void clear() {
    // 操作次数加1
    modCount++;

    // clear to let GC do its work
    // 循环将数组置为空
    for (int i = 0; i < size; i++)
        elementData[i] = null;
    // 成员变量 size 变为 0
    size = 0;
}
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
 / ** *以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。 * * <p>返回的数组将是“安全的”,因为此列表不保留对其的引用。 (换句话说,此方法必须分配*一个新数组)。因此,调用者可以自由修改返回的数组。 * * <p>此方法充当基于数组的API和基于集合的API之间的桥梁。 * * @以正确的顺序返回包含此列表中所有元素的数组* /
 */
public Object[] toArray() {
    //                   需要复制的数组, 需要复制的长度
    return Arrays.copyOf(elementData, size);
}
addAll
/**
 * 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
 / ** *按指定集合的​​Iterator返回的顺序,将指定集合中的所有元素追加到此列表的末尾。如果在操作过程中修改了指定的集合,则该操作的行为是不确定的。 (这意味着如果指定的集合是此列表,并且此列表是非空的,则此调用的行为是* undefined。)* * @param c集合,其中包含要添加到此列表的元素* @return <tt> true < / tt>如果此列表由于调用而更改* @throws NullPointerException如果指定的集合为null * /
 */
public boolean addAll(Collection<? extends E> c) {
    // 将集合转为一个复制后的数组
    Object[] a = c.toArray();
    // 获取数组长度
    int numNew = a.length;
    // 判断现在的集合是否存的下size + numNew 长的数据
    ensureCapacityInternal(size + numNew);  // Increments modCount
    // 复制
    System.arraycopy(a, 0, elementData, size, numNew);
    // 更改下标
    size += numNew;
    // 返回此次是否做了更改
    return numNew != 0;
}
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
        以正确的顺序返回此列表中元素的迭代器。
        <p>返回的迭代器为<a href="#fail-fast">
        <i>失败快速</ i> </a>。
        以正确的顺序返回此列表中元素的迭代器
     */
    public Iterator<E> iterator() {
        // new 了一个实现了 Iterator接口的内部类
        return new Itr();
    }
    /**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {
        int cursor;       //下一个要返回的元素的索引
        int lastRet = -1; //返回的最后一次取出的元素索引; -1(如果没有)
        // 保存 modCount 修改的次数
        int expectedModCount = modCount;
        // 是否还有下一个
        public boolean hasNext() {
            // cursor默认值为0 
            return cursor != size;
        }
        // 下一个数据
        @SuppressWarnings("unchecked")
        public E next() {
            // 检查是数组是否被修改
            checkForComodification();
            // 取得元素的下标索引,从0开始
            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() {
            // 判断有没有取出过元素,lastRet代表最后一次取出的元素索引,没取出过默认值为-1
            if (lastRet < 0)
                throw new IllegalStateException();
            // 检查运行期间数组状态是否发生了变动
            checkForComodification();
            
            try {
                // 尝试调用普通的下标删除方法去删除,最后一次取出的元素索引。
                ArrayList.this.remove(lastRet);
                // 下标回滚一次,因为底层数组已经重排序
                cursor = lastRet;
                // 最后一次取出的元素也往前推一个,当前元素删除,经过重排序,现在的lastRet为删除前的元素值,没有取出过,需要往前推一个
                lastRet = -1;
                // 更新操作次数,因为此次状态的变化是自己调用 remove产生的记过。
                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();
        }
        
        // 检查迭代期间内部数组有没有发生过状态的变化,发生了变化就快速失败抛出             
        // ConcurrentModificationException
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值