ArrayList 源码解读

ArrayList 源码解读

1、ArrayList 继承关系

ArrayList 继承树

ArrayList 继承了 AbstractList 抽象类,实现了 List 接口、RandomAccess 接口、Cloneable 接口、java.io.Serializable 接口

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

image-20210228140839163

1、List 接口

List接口的特点:

  1. 有序的集合,存储元素和取出元素的顺序是一致的
  2. 有索引,包含了一些带索引的方法
  3. 允许存储重复的元素

image-20210228141032211


List 接口常用的方法

  1. 增:add(Object obj)
  2. 删:remove(int index) / remove(Object obj)
  3. 改:set(int index, Object ele)
  4. 查:get(int index)
  5. 插:add(int index, Object ele)
  6. 长度:size()
  7. 遍历:① Iterator迭代器方式;② 增强for循环;③ 普通的循环

2、AbstractList 抽象类

AbstractList 抽象父类中:有些方法已经被赋予了具体的实现逻辑,比如 indexOf()lastIndexOf() 方法;而有些方法则需要推迟到子类中去实现,比如 get()set()add()remove() 等方法

/**
 * {@inheritDoc}
 *
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
abstract public E get(int index);

/**
 * {@inheritDoc}
 *
 * <p>This implementation always throws an
 * {@code UnsupportedOperationException}.
 *
 * @throws UnsupportedOperationException {@inheritDoc}
 * @throws ClassCastException            {@inheritDoc}
 * @throws NullPointerException          {@inheritDoc}
 * @throws IllegalArgumentException      {@inheritDoc}
 * @throws IndexOutOfBoundsException     {@inheritDoc}
 */
public E set(int index, E element) {
    
    
    throw new UnsupportedOperationException();
}

/**
 * {@inheritDoc}
 *
 * <p>This implementation always throws an
 * {@code UnsupportedOperationException}.
 *
 * @throws UnsupportedOperationException {@inheritDoc}
 * @throws ClassCastException            {@inheritDoc}
 * @throws NullPointerException          {@inheritDoc}
 * @throws IllegalArgumentException      {@inheritDoc}
 * @throws IndexOutOfBoundsException     {@inheritDoc}
 */
public void add(int index, E element) {
    
    
    throw new UnsupportedOperationException();
}

/**
 * {@inheritDoc}
 *
 * <p>This implementation always throws an
 * {@code UnsupportedOperationException}.
 *
 * @throws UnsupportedOperationException {@inheritDoc}
 * @throws IndexOutOfBoundsException     {@inheritDoc}
 */
public E remove(int index) {
    
    
    throw new UnsupportedOperationException();
}


// Search Operations

/**
 * {@inheritDoc}
 *
 * <p>This implementation first gets a list iterator (with
 * {@code listIterator()}).  Then, it iterates over the list until the
 * specified element is found or the end of the list is reached.
 *
 * @throws ClassCastException   {@inheritDoc}
 * @throws NullPointerException {@inheritDoc}
 */
public int indexOf(Object o) {
    
    
    ListIterator<E> it = listIterator();
    if (o==null) {
    
    
        while (it.hasNext())
            if (it.next()==null)
                return it.previousIndex();
    } else {
    
    
        while (it.hasNext())
            if (o.equals(it.next()))
                return it.previousIndex();
    }
    return -1;
}

/**
 * {@inheritDoc}
 *
 * <p>This implementation first gets a list iterator that points to the end
 * of the list (with {@code listIterator(size())}).  Then, it iterates
 * backwards over the list until the specified element is found, or the
 * beginning of the list is reached.
 *
 * @throws ClassCastException   {@inheritDoc}
 * @throws NullPointerException {@inheritDoc}
 */
public int lastIndexOf(Object o) {
    
    
    ListIterator<E> it = listIterator(size());
    if (o==null) {
    
    
        while (it.hasPrevious())
            if (it.previous()==null)
                return it.nextIndex();
    } else {
    
    
        while (it.hasPrevious())
            if (o.equals(it.previous()))
                return it.nextIndex();
    }
    return -1;
}

3、RandomAccess 接口

RandomAccess 这个接口很有趣,里面并没有定义任何方法规范,是个空接口。RandomAccess 接口是一个标志接口(Marker),只要 List 集合实现这个接口,就能支持快速随机访问(类似于数组那样根据索引下标进行访问)

public interface RandomAccess {
    
    
}

4、Cloneable 接口

Cloneable 这个借口也是个空接口(标志接口),我们要使用一个对象的 clone()方法,必须实现 Cloneable 接口,这个接口没有任何实现,跟 RandomAccess一样是一种标志性接口,如果不实现 Cloneable 接口,会抛出 CloneNotSupportedException 异常

其实吧,并不是 Cloneable 借口没有对应的方法规范,而是 JDK 编写者觉得所有对象都应该有 clone() 这种行为规范,于是将这种共同的行为规范提取到 Object 类中去了~

public interface Cloneable {
    
    
}

5、java.io.Serializable 接口

哇塞塞,又是一个标志性接口,Serializable 接口是启用其序列化功能的接口。实现 java.io.Serializable 接口的类是可序列化的。没有实现此接口的类将不能使它们的任意状态被序列化或逆序列化。

实现 java.io.Serializable 这个接口是为序列化,serialVersionUID 用来表明实现序列化类的不同版本间的兼容性。如果你修改了此类,要修改此值。

public interface Serializable {
    
    
}

我们可以在 ArrayList 的源码中看到此 serialVersionUID

image-20210228144400331

2、ArrayList 的初始容量

ArrayList 的空参构造方法

注释说:Constructs an empty list with an initial capacity of ten.,即构造一个初始容量为 10 的 ArrayList

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    
    
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

构造器中的字段

elementData 就是用来存放实际数据的数组,可以看到这是一个 Object[] 类型的数组,也就是说什么类型的数据也能往这个数组里面放,因为 Object 类是所有类的顶级父类。字段使用 transient 关键字修饰,表示在类的实例对象的序列化处理过程中会被忽略

DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是个空数组啊,为啥构造器的注释写写着构造了一个初始容量为 10 的数组,别着急,往下看

来看看 elementData 字段上面的注释: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.,当第一个元素被添加时,数组容量将被扩充到 10

/**
 * 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.
 */
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.
 */
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;

3、ArrayList#add() 方法

添加元素的方法:boolean add(E e) 方法

方法注释:Appends the specified element to the end of this list,即将一个指定的元素添加到 ArrayList 集合的尾部;并返回是否添加成功

ensureCapacityInternal(size + 1) 实现 ArrayList 的扩容

elementData[size++] = e 负责将元素添加到 ArrayList 集合尾部,并将集合元素个数 size 加 1

/**
 * 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) {
    
    
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

扩容方法:ensureCapacityInternal(size + 1) 方法

形参为 minCapacity,也就是刚才的 size + 1,表示 ArrayList 所需的最小容量

这里有个很重要的判断:我们在构造器初始化时,将 this.elementData 赋值为 DEFAULTCAPACITY_EMPTY_ELEMENTDATA,因此 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) 判断成立(即 elementData 数组为空数组),所以就会执行 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity) 方法。第一次执行 add() 方法,集合元素个数 size = 0,因此 minCapacity =DEFAULT_CAPACITY = 10。这就是上面所讲的当第一个元素被添加时,数组容量将被扩充到 10

接下来便执行 ensureExplicitCapacity(minCapacity) 方法将数组容量扩充到 10

private void ensureCapacityInternal(int minCapacity) {
    
    
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    
    
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

扩容方法:ensureExplicitCapacity(minCapacity) 方法

首先执行 modCount++ 标记 ArrayList 已经被修改过了

if (minCapacity - elementData.length > 0):如果 ArrayList 所需容量已经超过 ArrayList 实际容量,则需要执行 grow(minCapacity) 方法进行扩容

private void ensureExplicitCapacity(int minCapacity) {
    
    
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

关于 modCount 变量

modCount 变量是在抽象父类 AbstractList 中定义的变量,用于标识集合是否被修改过(The number of times this list has been structurally modified.

扩容方法:grow(minCapacity) 方法

关键在这一个右移操作上:oldCapacity + (oldCapacity >> 1),这个操作会将当前数组的容量扩容为之前的 1.5 倍

接着进行一系列的安全检查后,执行 elementData = Arrays.copyOf(elementData, newCapacity) 方法将原来数组中的元素拷贝到数组中

/**
 * 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
 */
private void grow(int minCapacity) {
    
    
    // overflow-conscious code
    int oldCapacity = elementData.length;
    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;
}

4、ArrayList#get() 方法

获取指定索引处的元素:E get(int index) 方法

首先执行 rangeCheck(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);
}

边界检查:rangeCheck(int 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.
 */
private void rangeCheck(int index) {
    
    
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

5、ArrayList#remove() 方法

删除指定索引处的元素:E remove(int index) 方法

首先还是执行 rangeCheck(index) 进行边界检查

执行 modCount++ 指令标记集合已经被修改过了

执行 E oldValue = elementData(index) 方法取出指定索引处的元素

执行 System.arraycopy(elementData, index+1, elementData, index, numMoved) 方法,将数组后面的元素往前面移,实现覆盖删除的效果(index 索引处的元素被覆盖)

执行 elementData[--size] = null,将 elementData[size] 元素设置为 null,让 GC 回收掉 elementData[size] 元素指向的对象;同时 size 执行减 1 操作,集合元素个数减 1

最后将被删除的元素返回

/**
 * 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}
 */
public E remove(int index) {
    
    
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

6、ArrayList#set() 方法

设置指定索引处元素的值:E set(int index, E element) 方法

首先还是执行 rangeCheck(index) 进行边界检查,然后修改 index 索引处元素的值

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

// Positional Access Operations

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

7、ArrayList#indexOf() 方法

获取元素的索引:int indexOf(Object o) 方法

这里分为两种情况:o == nullo != null。当 o == null,判断相等使用 elementData[i]==null 进行判断;当 o != null,判断相等使用 o.equals(elementData[i]) 进行判断

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

8、ArrayList 迭代器

迭代器:Iterator 迭代器接口

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小

Java中的Iterator功能比较简单,并且只能单向移动

  1. 使用hasNext()检查序列中是否还有元素。
  2. 使用next()获得序列中的下一个元素。
  3. 使用remove()将迭代器新返回的元素删除。
public interface Iterator<E> {
    
    
    /**
     * Returns {@code true} if the iteration has more elements.
     * (In other words, returns {@code true} if {@link #next} would
     * return an element rather than throwing an exception.)
     *
     * @return {@code true} if the iteration has more elements
     */
    boolean hasNext();

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration
     * @throws NoSuchElementException if the iteration has no more elements
     */
    E next();

    /**
     * Removes from the underlying collection the last element returned
     * by this iterator (optional operation).  This method can be called
     * only once per call to {@link #next}.  The behavior of an iterator
     * is unspecified if the underlying collection is modified while the
     * iteration is in progress in any way other than by calling this
     * method.
     *
     * @implSpec
     * The default implementation throws an instance of
     * {@link UnsupportedOperationException} and performs no other action.
     *
     * @throws UnsupportedOperationException if the {@code remove}
     *         operation is not supported by this iterator
     *
     * @throws IllegalStateException if the {@code next} method has not
     *         yet been called, or the {@code remove} method has already
     *         been called after the last call to the {@code next}
     *         method
     */
    default void remove() {
    
    
        throw new UnsupportedOperationException("remove");
    }

    /**
     * Performs the given action for each remaining element until all elements
     * have been processed or the action throws an exception.  Actions are
     * performed in the order of iteration, if that order is specified.
     * Exceptions thrown by the action are relayed to the caller.
     *
     * @implSpec
     * <p>The default implementation behaves as if:
     * <pre>{@code
     *     while (hasNext())
     *         action.accept(next());
     * }</pre>
     *
     * @param action The action to be performed for each element
     * @throws NullPointerException if the specified action is null
     * @since 1.8
     */
    default void forEachRemaining(Consumer<? super E> action) {
    
    
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

ArrayList 内部类:Itr 迭代器类

Iterator是Java迭代器最简单的实现,在 ArrayList 类中找到 Itr 类,该类实现了 Iterator 接口,并重写了其中的方法


Itr 中的字段

  1. cursor:下一个元素的索引
  2. lastRet:最近一次返回的元素的索引
  3. expectedModCount:期望的修改计数器
/**
 * 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;


boolean hasNext() 方法

如果下一个元素的索引 == 集合元素个数,则说明已经没有下一个元素了,那么 hasNext() 的条件为 cursor != size

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

E next() 方法

首先通过 checkForComodification() 方法检查集合是否已经被更改(modCount != expectedModCount),若已经被更改,则抛出 ConcurrentModificationException 异常。接着还有一些 Guard Safe 语句,就不多赘述

最后将游标 cursor 右移,准备访问下一个元素,将待访问的元素(elementData[i])返回,并将最近一次访问过的元素索引设置为 ilastRet = i

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

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

remove() 方法

Guard Safe:判断 lastRet(最近一次访问过的元素索引)是否存在,以及判断集合是够被修改过,若有上述情况,则抛出相应的异常

因为 Itr 类是 ArrayList 的内部类,通过 ArrayList.this.remove(lastRet) 这种方式调用当前 ArrayList 对象的 remove() 方法,实现删除操作

cursor = lastRet:因为是删除元素,不是访问元素,因此 cursor 无需移动,原地踏步即可

lastRet = -1:上除了上次访问的元素,那么上次访问的元素索引就没有啦,需要将 lastRet 设置为 -1

expectedModCount = modCount:删除了集合中的元素,modCount 会减 1,需要更新 expectedModCount 的值,否则下次操作时会抛出 ConcurrentModificationException 异常

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

forEachRemaining(Consumer<? super E> consumer) 方法

若没有其他线程争抢,那么执行 while (i != size && modCount == expectedModCount) 循环将会从 i 处遍历至集合尾部,并将集合元素传入消费者的 accept() 方法中进行消费

cursor = ilastRet = i - 1:更新游标信息和上一次访问的元素索引信息

最后执行 checkForComodification() 方法查看是否出现了并发修改异常

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

Consumer 接口

Consumer 是一个函数式接口,void accept(T t) 方法负责消费一个对象

@FunctionalInterface
public interface Consumer<T> {
    
    

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
    
    
        Objects.requireNonNull(after);
        return (T t) -> {
    
     accept(t); after.accept(t); };
    }
}

List 集合专用迭代器:ListIterator 接口

boolean hasPrevious():是否存在前一个元素

E previous():返回前一个元素

int nextIndex():下一个元素的索引

int previousIndex():前一个元素的索引

set(E e):设置元素的值

add(E e):添加元素

public interface ListIterator<E> extends Iterator<E> {
    
    
    // Query Operations

    /**
     * Returns {@code true} if this list iterator has more elements when
     * traversing the list in the forward direction. (In other words,
     * returns {@code true} if {@link #next} would return an element rather
     * than throwing an exception.)
     *
     * @return {@code true} if the list iterator has more elements when
     *         traversing the list in the forward direction
     */
    boolean hasNext();

    /**
     * Returns the next element in the list and advances the cursor position.
     * This method may be called repeatedly to iterate through the list,
     * or intermixed with calls to {@link #previous} to go back and forth.
     * (Note that alternating calls to {@code next} and {@code previous}
     * will return the same element repeatedly.)
     *
     * @return the next element in the list
     * @throws NoSuchElementException if the iteration has no next element
     */
    E next();

    /**
     * Returns {@code true} if this list iterator has more elements when
     * traversing the list in the reverse direction.  (In other words,
     * returns {@code true} if {@link #previous} would return an element
     * rather than throwing an exception.)
     *
     * @return {@code true} if the list iterator has more elements when
     *         traversing the list in the reverse direction
     */
    boolean hasPrevious();

    /**
     * Returns the previous element in the list and moves the cursor
     * position backwards.  This method may be called repeatedly to
     * iterate through the list backwards, or intermixed with calls to
     * {@link #next} to go back and forth.  (Note that alternating calls
     * to {@code next} and {@code previous} will return the same
     * element repeatedly.)
     *
     * @return the previous element in the list
     * @throws NoSuchElementException if the iteration has no previous
     *         element
     */
    E previous();

    /**
     * Returns the index of the element that would be returned by a
     * subsequent call to {@link #next}. (Returns list size if the list
     * iterator is at the end of the list.)
     *
     * @return the index of the element that would be returned by a
     *         subsequent call to {@code next}, or list size if the list
     *         iterator is at the end of the list
     */
    int nextIndex();

    /**
     * Returns the index of the element that would be returned by a
     * subsequent call to {@link #previous}. (Returns -1 if the list
     * iterator is at the beginning of the list.)
     *
     * @return the index of the element that would be returned by a
     *         subsequent call to {@code previous}, or -1 if the list
     *         iterator is at the beginning of the list
     */
    int previousIndex();


    // Modification Operations

    /**
     * Removes from the list the last element that was returned by {@link
     * #next} or {@link #previous} (optional operation).  This call can
     * only be made once per call to {@code next} or {@code previous}.
     * It can be made only if {@link #add} has not been
     * called after the last call to {@code next} or {@code previous}.
     *
     * @throws UnsupportedOperationException if the {@code remove}
     *         operation is not supported by this list iterator
     * @throws IllegalStateException if neither {@code next} nor
     *         {@code previous} have been called, or {@code remove} or
     *         {@code add} have been called after the last call to
     *         {@code next} or {@code previous}
     */
    void remove();

    /**
     * Replaces the last element returned by {@link #next} or
     * {@link #previous} with the specified element (optional operation).
     * This call can be made only if neither {@link #remove} nor {@link
     * #add} have been called after the last call to {@code next} or
     * {@code previous}.
     *
     * @param e the element with which to replace the last element returned by
     *          {@code next} or {@code previous}
     * @throws UnsupportedOperationException if the {@code set} operation
     *         is not supported by this list iterator
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this list
     * @throws IllegalArgumentException if some aspect of the specified
     *         element prevents it from being added to this list
     * @throws IllegalStateException if neither {@code next} nor
     *         {@code previous} have been called, or {@code remove} or
     *         {@code add} have been called after the last call to
     *         {@code next} or {@code previous}
     */
    void set(E e);

    /**
     * Inserts the specified element into the list (optional operation).
     * The element is inserted immediately before the element that
     * would be returned by {@link #next}, if any, and after the element
     * that would be returned by {@link #previous}, if any.  (If the
     * list contains no elements, the new element becomes the sole element
     * on the list.)  The new element is inserted before the implicit
     * cursor: a subsequent call to {@code next} would be unaffected, and a
     * subsequent call to {@code previous} would return the new element.
     * (This call increases by one the value that would be returned by a
     * call to {@code nextIndex} or {@code previousIndex}.)
     *
     * @param e the element to insert
     * @throws UnsupportedOperationException if the {@code add} method is
     *         not supported by this list iterator
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this list
     * @throws IllegalArgumentException if some aspect of this element
     *         prevents it from being added to this list
     */
    void add(E e);
}

ArrayList 的内部类:ListItr 迭代器类

ListItr 类继承了 Itr 类,并实现了 ListIterator 接口,它可以从两个方向遍历 List,也可以从 List 中插入和删除元素。

至于源码方面和 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();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/oneby1314/article/details/114230269