ArrayList 源码分析

可紊 提交于 2021-02-20 01:02:23

ArrayList 是 Java 中非常常用的数据结构,其底层基于 Object[] 数组实现,其特点是:基于 Object[] 数组,查询快,可随机访问,可以动态增加容量,增加和删除慢,线程不安全

ArrayList 是线程不安全的,在多线程环境下推荐使用 CopyOnWriteArrayList 或者 Vector

下图显示的 ArrayList 的继承关系图:

  • 实现 Cloneable 接口,覆写其 clone() 方法,实现数组元素的克隆;
  • 实现 Serializable 接口,表示这可以系列化传输
  • 实现 RandomAccess 接口,表示实现这个接口的 List 支持随机访问,也就是通过 index 序号快速获取元素;
  • 继承 AbstractList ,AbstractList 是一个数组队列,提供了添加、删除、修改、遍历等功能;

ArrayList

1、ArrayList 核心代码

1.1、ArrayList 的构造方法

/** 默认初始容量 */
private static final int DEFAULT_CAPACITY = 10;
/** 默认的空数组实例,用于初始化容量为零的数组 */
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
 * 默认的空数组实例,用于初始化容量为零的数组
 * 但插入第一条数据的时候会判断是否等于这个数组,如果是,直接扩展为默认容量
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/** 存储实际的数据的数组 */
transient Object[] elementData; // non-private to simplify nested class access
/** 所包含的元素个数 */
private int size;
/**
 * 初始化指定容量的数组
 */
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);
    }
}

/**
 * 无参构造函数,初始化为一个空数组
 * 但插入第一个数据的时候,如果 elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA 初始化为默认容量为 10
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

/**
 * 构造包含指定集合的元素的的列表
 */
public ArrayList(Collection<!--? extends E--> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray 可能不是返回 Object[] 类型
        if (elementData.getClass() != Object[].class) {
            // 将原来不是 Object[]类型的数组转换为 Object[]
            elementData = Arrays.copyOf(elementData, size, Object[].class);
        }
    } else {
        // 长度等于 0 用空数组代替
        this.elementData = EMPTY_ELEMENTDATA;
    }
}
  • 上面的无参构造函数,实际上会初始化一个空的数组,当对数组进行增加操作时候,才会真正将数组扩容为为默认 10 。也就是说,当向数组添加第一个元素的时候,才会将数组的容量扩充为 10

1.2、Array 扩容机制

> 这里以 JDK 11 为例,JDK 1.8 和 JDK 11 关于扩容的代码差异比较大,但其核心的逻辑结构是一样的。

  • 在调用 ArrayList 增加元素的方法时,如果数组当前的大小等于数组的容量,则调用 grow() 方法扩容
private void add(E e, Object[] elementData, int s) {
    // 如果数组的大小已经等于容量了,就使用 grow 方法扩容
    if (s == elementData.length)
        elementData = grow();
    elementData[s] = e;
    size = s + 1;
}
// 往数组的末尾增加一个元素
public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;
}
  • grow() 方法:
private Object[] grow(int minCapacity) {
    // newCapacity(minCapacity) 计算数组的最小扩容容量
    return elementData = Arrays.copyOf(elementData,
                                       newCapacity(minCapacity));
}
private Object[] grow() {
    return grow(size + 1);
}
  • newCapacity(minCapacity)
private int newCapacity(int minCapacity) {
    // overflow-conscious code
  	// 旧的容量
    int oldCapacity = elementData.length;
    // 计算新数组的容量,约等于旧数组的 1.5 倍
    // &gt;&gt; 不带符号的右移运算符,比整除运算快,右移 1 位约为原来的一半
    int newCapacity = oldCapacity + (oldCapacity &gt;&gt; 1);
  	// 如果 newCapacity 小于等于 minCapacity
    if (newCapacity - minCapacity &lt;= 0) {
      	// 如果是 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
      	// 这里也就是为什么无参构造函数增加增加一个数据后,数组的容量变成默认容量 10
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
          	// 1、无参构造函数函数构造的 ArrayList,size 为 0
          	// 2、使用 add 增加一个元素的时候,调用 grow 扩容
          	// 3、max(10,size + 1 = 1),所以第一次 add 增加一个元素的时候容量会为 10
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        if (minCapacity &lt; 0) // overflow
            throw new OutOfMemoryError();
        return minCapacity;
    }
  	// 如果 newCapacity 大于 minCapacity
    return (newCapacity - MAX_ARRAY_SIZE &lt;= 0)
        // 如果 newCapacity 大于等于 MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)
        ? newCapacity
      	// 比较 minCapacity 跟 MAX_ARRAY_SIZE 的大小
        : hugeCapacity(minCapacity);
}

private static int hugeCapacity(int minCapacity) {
    // 比较 minCapacity 跟 MAX_ARRAY_SIZE 的大小
    // 如果大于则 Integer.MAX_VALUE,否则 MAX_ARRAY_SIZE
    if (minCapacity &lt; 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity &gt; MAX_ARRAY_SIZE)
        ? Integer.MAX_VALUE
        : MAX_ARRAY_SIZE;
}

1.2.1、ensureCapacity 方法

ensureCapacity 这个方法在 ArraryList 中没有被调用过,主要是在增加大量元素前,最好在初始化的时候指定容量或者先调用一下这个方法,减少 ArrayList 扩容的次数和数组 Arrays.copyOf() 拷贝的次数

public void ensureCapacity(int minCapacity) {
    if (minCapacity &gt; elementData.length
        &amp;&amp; !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
             &amp;&amp; minCapacity &lt;= DEFAULT_CAPACITY)) {
        modCount++;
        grow(minCapacity);
    }
}

测试:

ArrayList<integer> list = new ArrayList&lt;&gt;();
int n = 10000000;
long start = System.currentTimeMillis();
// 注释或者去掉注释 ensureCapacity 分别运行代码
// 注释后 耗时:313
// 去掉注释 耗时:226
list.ensureCapacity(n);
for (int i = 0; i &lt; n; i++) {
    list.add(i);
}
long end = System.currentTimeMillis();
System.out.println("耗时:"+(end - start));

扩容的核心逻辑:

  • 如果 size 等于 elementData.length ,则进行扩容
  • 无参构造函数的List 调用 add 增加一个元素的时候,其容量会扩展为默认容量大小,也就是 10
  • 其他情况下,将 List 扩容为先前的约 1.5 倍
  • 假设现在的 ArrayList<>(10),也就是容量为 10,增加第 1、2、3....9、10 个元素的时候不会扩容,增加第十一个元素的时候,会扩容我原来的约 1.5倍,也就是容量为 15。

**ArrayList 源码 JDK 1.8 **:

> JDK 11 的改动比较大,主要是扩容方面的代码,上面有分析

public class ArrayList<e> extends AbstractList<e>
        implements List<e>, RandomAccess, Cloneable, java.io.Serializable {
    private static final long serialVersionUID = 8683452581122892189L;
    /**
     * 默认初始容量
     */
    private static final int DEFAULT_CAPACITY = 10;
    /**
     * 默认的空数组实例,用于初始化容量为零的数组
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};
    /**
     * 默认的空数组实例,用于初始化容量为零的数组
     * 但插入第一条数据的时候会判断是否等于这个数组,如果是,直接扩展为默认容量
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    /**
     * 存储实际的数据的数组
     */
    transient Object[] elementData; // non-private to simplify nested class access
    /**
     * 所包含的元素个数
     */
    private int size;
    /**
     * 初始化指定容量的数组
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity &gt; 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: " +
                    initialCapacity);
        }
    }

    /**
     * 无参构造函数,初始化为一个空数组
     * 但插入第一个数据的时候,如果 elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA 初始化为默认容量为 10
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * 构造包含指定集合的元素的的列表
     */
    public ArrayList(Collection<!--? extends E--> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray 可能不是返回 Object[] 类型
            if (elementData.getClass() != Object[].class) {
                // 将原来不是 Object[]类型的数组转换为 Object[]
                elementData = Arrays.copyOf(elementData, size, Object[].class);
            }
        } else {
            // 长度等于 0 用空数组代替
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

    /**
     * 去除数组中多余的空间,将数组的容量跟大小一样
     * 如果数组大小为 0 则是空数组
     */
    public void trimToSize() {
        // 记录修改次数
        modCount++;
        if (size &lt; elementData.length) {
            elementData = (size == 0)
                    ? EMPTY_ELEMENTDATA
                    : Arrays.copyOf(elementData, size);
        }
    }

    /**
     * 确保有足够的容量来容纳元素
     * minCapacity 当前数组所需的最小容量
     */
    public void ensureCapacity(int minCapacity) {
        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 &gt; minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    /**
     * 计算当前最小需要扩容容量,
     */
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // DEFAULTCAPACITY_EMPTY_ELEMENTDATA 午餐构造函数构造成这个
            // 所以说使用这个构造方法的数组添加第一个元素后,数组的容量变成 DEFAULT_CAPACITY = 10
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    /**
     * 再 add 等增加元素的方法中,调用这个方法判断数组是否有足够的容量容纳数据
     */
    private void ensureCapacityInternal(int minCapacity) {
        // calculateCapacity 计算数组所需的最小容量
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    /**
     * 如果当前数组容量小于最小容量,对数组进行扩容
     * @param minCapacity 最小所需的容量
     */
    private void ensureExplicitCapacity(int minCapacity) {
        // 修改次数 +1
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length &gt; 0)
            // 增加数组的容量,扩容
            grow(minCapacity);
    }

    /**
     * 最大的数组容量 2 的 31 次方 - 9
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * ArrayList 扩容的核心代码
     */
    private void grow(int minCapacity) {
        // 获取旧数组的容量
        int oldCapacity = elementData.length;
        // 计算新数组的容量,约等于旧数组的 1.5 倍
        // &gt;&gt; 带符号的右移运算符,比整除运算快,右移 1 位约为原来的一半
        // 偶数右移 1 位等于 x / 2
        // 奇数右移 1 位等于 (x -1) / 2
        int newCapacity = oldCapacity + (oldCapacity &gt;&gt; 1);
        // 如果数组新的容量小于最小所需的容量
        if (newCapacity - minCapacity &lt; 0)
            newCapacity = minCapacity;
        // 如果数组的新容量大于 MAX_ARRAY_SIZE
        if (newCapacity - MAX_ARRAY_SIZE &gt; 0)
            // 比较 minCapacity 跟 MAX_ARRAY_SIZE 的大小
            // 如果大于则 Integer.MAX_VALUE,否则 MAX_ARRAY_SIZE
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    // 比较 minCapacity 跟 MAX_ARRAY_SIZE 的大小
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity &lt; 0) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity &gt; MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
    }

    /**
     * 返回当前数组的大小,也就是包含多少个数组
     */
    public int size() {
        return size;
    }

    /**
     * 如果当前数组的大小为 0 ,则返回 true
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 返回数组中是否包含某个元素
     */
    public boolean contains(Object o) {
        return indexOf(o) &gt;= 0;
    }

    /**
     * 如果数组包含某个元素,则返回其索引,否则返回 -1
     */
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i &lt; size; i++)
                if (elementData[i] == null)
                    return i;
        } else { // 循环遍历,然后使用 equals 比较
            for (int i = 0; i &lt; size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    /**
     * 返回指定元素在数组中最大的索引值,没有该元素就返回 -1
     */
    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size - 1; i &gt;= 0; i--)
                if (elementData[i] == null)
                    return i;
        } else {
            for (int i = size - 1; i &gt;= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    /**
     * ArrayList 的克隆方法
     */
    public Object clone() {
        try {
            // 浅拷贝,元素数组并不会拷贝
            ArrayList<!--?--> v = (ArrayList<!--?-->) super.clone();
            // 拷贝数组
            v.elementData = Arrays.copyOf(elementData, size);
            // 修改次数为 0
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // 这不应该发生的,因为 Array 实现了 Cloneable
            throw new InternalError(e);
        }
    }

    /**
     * 将数组拷贝一份,返回(数组中元素的顺序不会变化)
     * 返回并不是 this.elementData 的引用,而是其拷贝
     * 因此在修改返回的数组不会影响 this.elementData 的数据
     */
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    /**
     * 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素)
     */
    @SuppressWarnings("unchecked")
    public <t> T[] toArray(T[] a) {
        // 如果 a 的容量小于 this.elementData 的大小
        if (a.length &lt; size)
            // 将 ArrayList 的内容拷贝一份,然后使用 T[] 类型返回
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        // a 的容量大于或等于 this.elementData 的大小
        // 使用 System.arraycopy() 将 elementData 的内容拷贝给 a
        // System.arraycopy 实现数组之间的拷贝,Arrays.copyOf 依赖于此方法
        System.arraycopy(elementData, 0, a, 0, size);
        // 如果 a 的容量大于 size,则 a[size] = null
        // 只有在调用者直到数组中不包含 null 的时候才能够确定其长度,
        if (a.length &gt; size)
            a[size] = null;
        return a;
    }

    /**
     * 返回指定 index 的元素
     */
    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

    /**
     * 返回指定 index 的元素
     */
    public E get(int index) {
        // 检查 index 是否符合规范
        rangeCheck(index);
        return elementData(index);
    }

    /**
     * 替换指定位置的元素
     */
    public E set(int index, E element) {
        // 检查 index
        rangeCheck(index);
        // 获取旧的元素
        E oldValue = elementData(index);
        // 替代旧的元素
        elementData[index] = element;
        return oldValue;
    }

    /**
     * 再数组最后增加一个元素
     */
    public boolean add(E e) {
        // 计算是否需要扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

    /**
     * 在指定位置插入元素
     */
    public void add(int index, E element) {
        // 检查 index
        rangeCheckForAdd(index);
        // 计算是否需要扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 使用 System.arraycopy 将 index 及其之后的元素后移一位
        System.arraycopy(elementData, index, elementData, index + 1,
                size - index);
        // index 设置为指定的元素
        elementData[index] = element;
        size++;
    }

    /**
     * 移除指定 index 的元素
     */
    public E remove(int index) {
        rangeCheck(index);
        modCount++;
        // 旧的元素
        E oldValue = elementData(index);
        // numMoved 等于 0 表示最后一个元素
        int numMoved = size - index - 1;
        if (numMoved &gt; 0)
            // index 之后的元素前移一位
            System.arraycopy(elementData, index + 1, elementData, index,
                    numMoved);
        elementData[--size] = null; // clear to let GC do its work
        return oldValue;
    }

    /**
     * 移除指定元素,第一个出现的,返回 true 表示包含指定的元素,并成功移除了第一个
     */
    public boolean remove(Object o) {
        // 如果指定元素等于 null
        if (o == null) {
            // 遍历,
            for (int index = 0; index &lt; size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index &lt; size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    /**
     * 移除指定 index 的元素
     */
    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved &gt; 0)
            System.arraycopy(elementData, index + 1, elementData, index,
                    numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

    /**
     * 情况数组中所有的元素
     */
    public void clear() {
        modCount++;
        // clear to let GC do its work
        for (int i = 0; i &lt; size; i++)
            elementData[i] = null;
        // 大小变成 0
        size = 0;
    }

    /**
     * 将集合的元素添加到 elementData 的末尾
     */
    public boolean addAll(Collection<!--? extends E--> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    /**
     * 将集合的元素添加到指定 index 之后
     */
    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 &gt; 0)
            // 如果要移动原数组,就像原数组后移
            System.arraycopy(elementData, index, elementData, index + numNew,
                    numMoved);
        // 将指定集合 a 的元素复制到 elementData 的 index 之后
        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);
        // clear to let GC do its work
        int newSize = size - (toIndex - fromIndex);
        for (int i = newSize; i &lt; size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

    /**
     * 检查 index 是否符合要求
     */
    private void rangeCheck(int index) {
        if (index &gt;= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * 也是检查 index 是否符合范围,增加数据的时候使用
     */
    private void rangeCheckForAdd(int index) {
        if (index &gt; size || index &lt; 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * 返回 IndexOutOfBoundsException 细节信息
     */
    private String outOfBoundsMsg(int index) {
        return "Index: " + index + ", Size: " + size;
    }

    /**
     * 从 elementData 删除指定集合中 c 交集的元素
     */
    public boolean removeAll(Collection<!--?--> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

    /**
     * 从 elementData 仅保留指定集合 c 中交集的元素
     */
    public boolean retainAll(Collection<!--?--> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

    /**
     * 上面两个函数调用的如果修改了则返回 true
     */
    private boolean batchRemove(Collection<!--?--> c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r &lt; 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 &lt; 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 {
        // Write out element count, and any hidden stuff
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioural compatibility with clone()
        s.writeInt(size);

        // Write out all elements in the proper order.
        for (int i = 0; i &lt; 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;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size &gt; 0) {
            // be like clone(), allocate array based upon size not capacity
            int capacity = calculateCapacity(elementData, size);
            SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i = 0; i &lt; size; i++) {
                a[i] = s.readObject();
            }
        }
    }

    /**
     * 从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。
     * 指定的索引表示初始调用将返回的第一个元素为next 。 初始调用previous将返回指定索引减1的元素。
     * 返回的列表迭代器是 fail-fast ,fail-safe 允许在遍历的过程中对容器中的数据进行修改,而fail-fast则不允许
     * https://blog.csdn.net/chenssy/article/details/38151189
     */
    public ListIterator<e> listIterator(int index) {
        if (index &lt; 0 || index &gt; size)
            throw new IndexOutOfBoundsException("Index: " + index);
        return new ListItr(index);
    }

    /**
     *  返回列表中的列表迭代器(按适当的顺序)。
     *  返回的列表迭代器是fail-fast
     */
    public ListIterator<e> listIterator() {
        return new ListItr(0);
    }

    /**
     * 以正确的顺序返回该列表中的元素的迭代器。
     * 返回的迭代器是 fail-fast 。
     */
    public Iterator<e> iterator() {
        return new Itr();
    }
}

</e></e></e></t></e></e></e></integer>

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!