Java 集合框架(2)---- List 相关类解析(上)

本文标题大纲:

前言

在上篇文章 Java 集合框架(1)— 概述 中我们从大体上看了一下 Java 中的集合框架,包括 ListSetMap 接口的一些介绍并且解释了一些接口中声明的相关方法用法。从这篇开始,我们将一起来看一下 Java 集合框架中一些具体的类的解析,了解它们的运行原理。先从 List 接口下的相关类开始。

Java 集合框架
还是先看一下上篇文章中的那张图,我们可以看到:在 Collection 接口下有一个名为 AbstractCollection 的抽象类,而 List 接口和 Set 接口下的具体类都直接 / 间接的继承了这个抽象类,我们还是先看一下这个抽象类:

AbstractCollection

来看看官方对这个类的描述:
This class provides a skeletal implementation of the Collection interface, to minimize the effort required to implement this interface.

To implement an unmodifiable collection,
the programmer needs only to extend this class and provide implementations for the iterator and size methods.
(The iterator returned by the iterator method must implement hasNext and next.)

To implement a modifiable collection, the programmer must additionally override this class’s add method (which otherwise throws an UnsupportedOperationException), and the iterator returned by the iterator method must additionally implement its remove method.

The programmer should generally provide a void (no argument) and Collection constructor, as per the recommendation in the Collection interface specification.

The documentation for each non-abstract method in this class describes its implementation in detail. Each of these methods may be overridden if the collection being implemented admits a more efficient implementation.

大概意思是:
该类提供了 Collection 接口的骨架实现,以最小化实现该接口所需的代价。
要实现不可修改的集合,开发者只需要继承这个类并实现 iterator() 方法和 size() 方法,即返回一个迭代器(实现了 hasNextnext 方法)用于遍历集合和一个表示集合元素个数的值。
为了实现可修改的集合,开发者必须另外重写该类的 add 方法(否则抛出 UnsupportedOperationException 异常),迭代器方法返回的迭代器还必须实现其 remove 方法。
开发者通常应该根据集合接口规范中的建议提供无参构造函数和以一个集合作为参数的构造函数。
该类中的每个非抽象方法的文档详细描述了它的实现。如果所实现的集合允许更有效的实现,则可以重写这些方法。

我们可以从上面的解释中的到一些信息:
1、这个类实现了 Collection 接口并且实现了一些集合通用的方法,这样的话具体集合类就可以直接 / 间接继承这个类,对一些已经实现的并且有效的方法无需再次实现,减轻了子类的负担;
2、继承这个类的子类必须重写其 iteratorsize 这两个抽象方法,并且重写其中所有实现的方法中直接抛出了 UnsupportedOperationException 异常的方法(add 方法)。
3、如果子类可以提供更有效的方法实现,设计者鼓励开发者在子类中复写其中的一些方法,以获取更高的执行效率。

如上所述,我们可以看到 ListSet 接口的下的具体类都是直接 / 间接继承了这个抽象类。
我们来看看这个类的一些源码:

public abstract class AbstractCollection<E> implements Collection<E> {
    // Query Operations

    /**
     * 返回一个包含了集合中所有元素的迭代器,用于遍历集合元素
     */
    public abstract Iterator<E> iterator();

    /**
     * 返回集合中元素的数量
     */
    public abstract int size();

    /**
     * 判断集合是否为空
     */
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * 查找当前集合中是否存在等价于参数的元素(通过 equals 方法)
     * 通过迭代器遍历集合并比对元素实现
     */
    public boolean contains(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return true;
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }

    /**
     * 这个方法返回包含集合中所有元素的数组,元素顺序通过迭代器遍历指定。
     * 方法等同于:
     * List<E> list = new ArrayList<E>(size());
     * for (E e : this)
     *     list.add(e);
     * return list.toArray();
     */
    public Object[] toArray() {
        // Estimate size of array; be prepared to see more or fewer elements
        Object[] r = new Object[size()];
        Iterator<E> it = iterator();
        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) // fewer elements than expected
                return Arrays.copyOf(r, i);
            r[i] = it.next();
        }
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    // Modification Operations

    /**
     * 添加参数所指定的对象到当前集合中,子类应该实现该方法
     */
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }

    /**
     * 从当前集合中移除第一个等价于参数的元素(通过 equals 方法判断等价),
     * 通过迭代器遍历集合中的元素并判断,如果移除成功返回 true,否则返回 false
     */
    public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext()) {
                if (it.next()==null) {
                    it.remove();
                    return true;
                }
            }
        } else {
            while (it.hasNext()) {
                if (o.equals(it.next())) {
                    it.remove();
                    return true;
                }
            }
        }
        return false;
    }


    // Bulk Operations

    /**
     * 判断参数 c 所指向的集合中每一个元素是否都包含在当前集合中,
     * 如果是,返回 true,否则返回 false
     */
    public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }

    /**
     * 将参数 c 所指向的集合中的每一个元素都添加到当前集合中,
     * 如果成功添加,返回 true,否则返回 false
     */
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }

    /**
     * 移除所有当前集合中存在于参数 c 所指向集合的元素,
     */
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

    /**
     * 求出当前集合和参数 c 代表的集合中元素的交集,
     * 通过迭代器遍历当前集合元素,判断每一个元素是否存在于集合 c 中,
     * 如果不存在,那么移除这个元素,如果参数 c 为 null,
     * 抛出 NullPointException 异常
     */
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

    /**
     * 通过当前集合的迭代器来移除集合中所有的元素
     */
    public void clear() {
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }
    }


    //  String conversion

    /**
     * 返回表示集合(元素)信息的字符串
     */
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

}

我们可以发现,这个接口中显式声明了两个抽象方法:iterator 方法用于获取遍历集合的迭代器,size 方法用于获取集合元素的数量。而其他实现的方法都是基于这两个方法之上,即都是使用了这两个方法(至少一个)来实现的(请注意:for each 语句也是通过迭代器实现的,在前篇文章我们已经讨论过了)。这中设计思想其实是典型的 模板方法(Template Method) 设计模式:在父类中声明一些必要的抽象方法,同时父类通过这些抽象方法来实现一些实例方法,而这个些抽象方法通过继承来交给子类实现,子类根据自己的特性来自定义实现这些抽象方法,以达到最好的执行效率。利用多态性来达到不同的子类有不同的行为的同时也保证了整个框架具有良好的扩展性。
顺应着上面的集合类继承框图,我们继续向下看:

AbstractList

下面我们来看一下 AbstractList 类,它继承了 AbstractCollection 类,同时也是 ArrayList 等具体集合类的父类。先来看一下官方的说明:

This class provides a skeletal implementation of the List interface to minimize the effort required to implement this interface backed by a “random access” data store (such as an array). For sequential access data (such as a linked list), AbstractSequentialList should be used in preference to this class.
To implement an unmodifiable list, the programmer needs only to extend this class and provide implementations for the get(int) and size() methods.
To implement a modifiable list, the programmer must additionally override the set(int, E) method (which otherwise throws an UnsupportedOperationException). If the list is variable-size the programmer must additionally override the add(int, E) and remove(int) methods.
The programmer should generally provide a void (no argument) and collection constructor, as per the recommendation in the Collection interface specification.
Unlike the other abstract collection implementations, the programmer does not have to provide an iterator implementation; the iterator and list iterator are implemented by this class, on top of the “random access” methods: get(int), set(int, E), add(int, E) and remove(int).
The documentation for each non-abstract method in this class describes its implementation in detail. Each of these methods may be overridden if the collection being implemented admits a more efficient implementation.

这份说明其实和上面的 AbstractCollection 类的说明差不多,也分几个点:
1、该类提供了 List 接口的骨架实现,以最大限度地减少实现由 “随机访问” 数据存储(如数组)所支持的接口所需的工作量。对于顺序访问数据(如链接列表),应该优先使用 AbstractSequentialList 类。
2、如果要实现一个不可修改的列表,程序员只需要扩展这个类并为 get(int)size() 方法提供实现。
要实现一个可修改的列表,程序员必须另外重写 set(int, E) 方法(否则抛出一个UnsupportedOperationException)。如果列表是可变大小,程序员必须另外重写 add(int, E)remove(int) 方法,即当前类并没有实现获取随机访问集合和修改集合元素信息的方法。
3、根据 Collection 接口规范中的建议,程序员通常应该提供一个无参构造函数和提供一个 Collection 接口对象作为参数的构造函数。
4、与其他抽象集合实现不同,这个类已经实现了 iterator() 方法,子类可以不必提供迭代器实现,对于某些方法,如果子类允许更有效的实现,设计者鼓励子类可以重写这些方法中的任何一个。

从上面的文档我们大概知道了这个类的功能,下面我们再看一下这个类的相关源代码:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {

    /**
     * 添加参数所指定的元素到当前列表末尾,某些集合可能不允许值为 null 的元素,
     * 通过调用重载方法 add(int, E) 来添加元素,当前类并没有实现该方法,
     * 抛出一个 UnsupportedOperationException 异常
     */
    public boolean add(E e) {
        add(size(), e);
        return true;
    }

    /**
     * 获取参数 index 所在下标的元素
     */
    abstract public E get(int index);

    /**
     * 设置参数 index 所在下标的元素为参数 element,
     * 默认抛出 UnsupportedOperationException 异常,
     * 如果需要实现可更改列表,子类应实现该方法
     */
    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }

    /**
     * 添加参数 element 所指定的元素到 index 所指定的下标
     */
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }

    /**
     * 移除集合中 index 所在下标指定的元素,
     * 默认抛出 UnsupportedOperationException 异常,
     * 如果子类想要实现可变大小的列表,那么应该实现这个方法
     */
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }


    // Search Operations

    /**
     * 通过 list 迭代器正向遍历列表,返回参数 o 所在集合中第一次出现的下标(通过 equals 方法判定),
     * 如果 o 没有在当前列表中出现,那么返回 -1
     */
    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;
    }

    /**
     * 通过 list 迭代器反向向遍历列表,返回参数 o 所在集合中最后一次出现的下标(通过 equals 方法判定),
     * 如果 o 没有在当前列表中出现,那么返回 -1
     */
    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;
    }


    // Bulk Operations

    /**
     * 移除列表中所有的元素,通过调用 removeRange(int, int) 实现,
     * removeRange(int, int) 方法默认抛出 UnsupportedOperationException 异常
     */
    public void clear() {
        removeRange(0, size());
    }

    /**
     * 从参数 index 下标开始,将集合 c 中所有的元素依次添加到当前列表中
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        boolean modified = false;
        for (E e : c) {
            add(index++, e);
            modified = true;
        }
        return modified;
    }


    // Iterators

    /**
     * 返回一个实现了 Iterator 接口的迭代器对象,用于遍历当前列表
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * 返回一个实现了 ListIterator (支持反向遍历)接口的迭代器对象,用于遍历当前列表
     */
    public ListIterator<E> listIterator() {
        return listIterator(0);
    }

    /**
     * 返回一个起始位置为 index 的 list 迭代器(第一次调用 next() 返回下标 index 所指向的元素),
     * 用于遍历当前列表,如果 index 越界,那么抛出一个 IndexOutOfBoundsException 异常
     */
    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }

    /**
     * 返回一个范围为 [fromIndex, toIndex) 的子列表,
     * 如果参数越界,那么抛出一个 IndexOutOfBoundsException 异常
     */
    public List<E> subList(int fromIndex, int toIndex) {
        return (this instanceof RandomAccess ?
                new RandomAccessSubList<>(this, fromIndex, toIndex) :
                new SubList<>(this, fromIndex, toIndex));
    }

    // Comparison and hashing

    /**
     * 判断当前列表和参数所指向的对象是否等价,如果参数 o 所指向的对象也是 List 对象,
     * 那么通过判断两个列表的长度是否相等和所有元素是否等价(通过 equals 方法)来决定。
     */
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof List))
            return false;

        ListIterator<E> e1 = listIterator();
        ListIterator<?> e2 = ((List<?>) o).listIterator();
        while (e1.hasNext() && e2.hasNext()) {
            E o1 = e1.next();
            Object o2 = e2.next();
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }
        return !(e1.hasNext() || e2.hasNext());
    }


    /**
     * 返回该列表对象的 hashCode ,通过列表中所有元素来计算
     */
    public int hashCode() {
        int hashCode = 1;
        for (E e : this)
            hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
        return hashCode;
    }

    /**
     * 移除列表中范围在 [fromIndex, toIndex) 中的元素
     */
    protected void removeRange(int fromIndex, int toIndex) {
        ListIterator<E> it = listIterator(fromIndex);
        for (int i=0, n=toIndex-fromIndex; i<n; i++) {
            it.next();
            it.remove();
        }
    }

    // ...
}

好吧,直到看到了这个类,我们才看到了一些更加符合线性结构特性的方法(get(int index)set(int index, E element)indexOf(Object o) ……)。而官方解释也说了这个类提供了 List 接口的骨架实现,以最大化减轻子类实现线性结构相关数据结构所需的工作量。如果要实现一个不可变(大小、元素值都不可变)的线性结构,我们只需要在子类中实现 get(int index) 抽象方法和 size() 方法就可以了。但是通常对于线性结构来说,仅仅能获取元素信息(get)是远远不够的,想一想,如果给你一个只能遍历元素的链表,而不能插入、删除、修改元素值,那么这个链表存在的意义也就不大了。为什么这么说呢?我们想想链表的优势是什么?熟悉数据结构的小伙伴可能一下就反应过来了:插入、删除元素操作很快,只需要 O(1) 的时间复杂度。确实,那么如果这个链表不能进行插入和删除操作,那我还不如用顺序表(数组)储存元素呢,还能节省节点指向前后节点的指针所耗费的内存空间。所以在 ArrayList LinkedList 类中我们可以看到它们都重写了 set(int index, E element)add(E element)remove(int index) …… 等方法用于修改当前列表的内容。我们将在后面的篇幅详细讨论这两种数据结构。

我们还注意到:在类的 iterator()listIterator(final int index) 方法中分别返回了一个 Itr 对象和一个 ListItr 对象,而根据这两个方法的返回值我们就可以知道 Itr 类应该直接 / 间接实现了 Iterator 接口,而 ListItr 类也应该直接 / 间接实现了 ListIterator 接口,我们来看看这两个类:

先是 AbstractList.Itr 类:

private class Itr implements Iterator<E> {
    /**
     * 下一次调用 next() 方法返回的元素所在下标
     */
    int cursor = 0;

    /**
     * 记录上一次调用 next() 方法返回的元素所在下标,
     * 如果调用 remove 方法移除上一次访问的元素,该变量应该重置为 -1
     */
    int lastRet = -1;

    /**
     * 记录当前列表元素更改次数,在每次更改列表元素之后该值应该进行更新
     */
    int expectedModCount = modCount;

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

    public E next() {
        checkForComodification();
        try {
            int i = cursor;
            E next = get(i);
            // 更新 lastRet 值
            lastRet = i;
            // 当前元素下标后移,为下一次 next 方法的调用做准备
            cursor = i + 1;
            return next;
        } catch (IndexOutOfBoundsException e) {
            checkForComodification();
            throw new NoSuchElementException();
        }
    }

    /**
     * 移除上一次调用 next() 方法返回的元素
     */
    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            AbstractList.this.remove(lastRet);
            if (lastRet < cursor)
                cursor--;
            // lastRet 值重置为 -1
            lastRet = -1;
            // 更新 expectedModCount 值
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException e) {
            throw new ConcurrentModificationException();
        }
    }

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

我们可以看到这个类是 AbstractList 类的私有内部类。其确实是实现了 Iterator 接口,用于正向遍历列表元素。关于 Iterator 接口我们在前一篇文章中已经讨论过了,小伙伴们可以去看一下上一遍文章。下面看看 ListItr 类:

AbstractList.ListItr :

private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        cursor = index;
    }

    public boolean hasPrevious() {
        return cursor != 0;
    }

    // 返回上一次调用 next() 所返回的元素
    public E previous() {
        checkForComodification();
        try {
            int i = cursor - 1;
            E previous = get(i);
            lastRet = cursor = i;
            return previous;
        } catch (IndexOutOfBoundsException e) {
            checkForComodification();
            throw new NoSuchElementException();
        }
    }

    // 获取下一个元素所在下标(下一次调用 next() 方法所返回元素所在下标)
    public int nextIndex() {
        return cursor;
    }

    // 获取上一次遍历的元素下标(上一次调用 next() 方法所返回的元素所在下标)
    public int previousIndex() {
        return cursor-1;
    }

    // 将上一次调用 next() 方法返回元素所在下标所指向的元素设为参数 e 
    public void set(E e) {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            AbstractList.this.set(lastRet, e);
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    /*
     * 在 cursor 的位置插入一个新元素 e,并将 cursor 后移一位,
     * 下一次调用 next() 方法的返回值不变。
     */
    public void add(E e) {
        checkForComodification();

        try {
            int i = cursor;
            AbstractList.this.add(i, e);
            // 重置 lastRet 值
            lastRet = -1;
            cursor = i + 1;
            // 更新 expectedModCount 值
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}

这个类继承了 Itr 类,并且实现了 ListIterator 接口,我们知道 ListIterator 接口是专门为 List 接口下的类提供的,其提供了反向遍历列表的能力,更加符合线性结构的逻辑结构特性,同样的,对这个接口有兴趣的小伙伴可以取看一下上一篇文章。

最后,上面 AbstractList 类的 subList 方法中出现了 SubList 类和 RandomAccessSubList 类的身影,这两个类是 AbstractList.java 文件中的非 public 型的类,并且这两个类是继承了 AbstractList 类的,既然是非 public 类型的类,也就是说我们在外面不能直接使用这两个类,只能在同类文件和相同包内的类中使用(其实我们就是不能直接用,因为其存在 Java 源码包内……)。我们来看看这两个类:

/**
 * 表示一个列表的子列表,表示范围:源列表下标范围: [fromIndex, toIndex)
 */
class SubList<E> extends AbstractList<E> {
    // 源列表对象
    private final AbstractList<E> l;
    // 当前列表中的开始元素下标相对列表第一个元素的偏移量
    private final int offset;
    // 当前列表的元素数量
    private int size;

    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > list.size())
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
        l = list;
        // 开始下标(偏移量)
        offset = fromIndex;
        // 元素数量
        size = toIndex - fromIndex;
        // 列表元素更改次数
        this.modCount = l.modCount;
    }

    public E set(int index, E element) {
        rangeCheck(index);
        checkForComodification();
        // 直接调用 AbstractList 对象的 set(int, E) 方法,
        // 通过加上偏移量来保证正确性
        return l.set(index+offset, element);
    }

    public E get(int index) {
        // 检查 index 下标是否越界,如果是,抛出 IndexOutOfBoundsException 异常
        rangeCheck(index);
        checkForComodification();
        // 同理,也是通过加上子列表的偏移量来保证正确性
        return l.get(index+offset);
    }

    public int size() {
        checkForComodification();
        return size;
    }

    public void add(int index, E element) {
        rangeCheckForAdd(index);
        checkForComodification();
        l.add(index+offset, element);
        this.modCount = l.modCount;
        size++;
    }

    public E remove(int index) {
        rangeCheck(index);
        checkForComodification();
        E result = l.remove(index+offset);
        this.modCount = l.modCount;
        size--;
        return result;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        l.removeRange(fromIndex+offset, toIndex+offset);
        this.modCount = l.modCount;
        size -= (toIndex-fromIndex);
    }

    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        int cSize = c.size();
        if (cSize==0)
            return false;

        checkForComodification();
        l.addAll(offset+index, c);
        this.modCount = l.modCount;
        size += cSize;
        return true;
    }

    public Iterator<E> iterator() {
        return listIterator();
    }

    // 返回当前列表的 ListIterator 迭代器对象
    public ListIterator<E> listIterator(final int index) {
        checkForComodification();
        rangeCheckForAdd(index);

        return new ListIterator<E>() {
            // 迭代器初始指向元素的位置为 index + 偏移量,
            // 迭代器的相关元素操作都需要计算偏移量 offset
            private final ListIterator<E> i = l.listIterator(index+offset);

            public boolean hasNext() {
                return nextIndex() < size;
            }

            public E next() {
                if (hasNext())
                    return i.next();
                else
                    throw new NoSuchElementException();
            }

            public boolean hasPrevious() {
                return previousIndex() >= 0;
            }

            public E previous() {
                if (hasPrevious())
                    return i.previous();
                else
                    throw new NoSuchElementException();
            }

            public int nextIndex() {
                return i.nextIndex() - offset;
            }

            public int previousIndex() {
                return i.previousIndex() - offset;
            }

            public void remove() {
                i.remove();
                SubList.this.modCount = l.modCount;
                size--;
            }

            public void set(E e) {
                i.set(e);
            }

            public void add(E e) {
                i.add(e);
                SubList.this.modCount = l.modCount;
                size++;
            }
        };
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new SubList<>(this, fromIndex, toIndex);
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

    private void checkForComodification() {
        if (this.modCount != l.modCount)
            throw new ConcurrentModificationException();
    }
}

/**
 * 继承自 SubList 类,并且实现了一个 RandomAccess 接口(空接口)
 */
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
        super(list, fromIndex, toIndex);
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new RandomAccessSubList<>(this, fromIndex, toIndex);
    }
}

可以看到,表示子列表的两个类并没有新建一个列表对象,而是创建一个字段指向源列表对象,并且将起始下标(fromIndex) 作为偏移量,而之后对子列表元素的相关操作都是通过调用源列表的相关方法并且算上偏移量(offset) 来实现的(委托的设计思想)。

好了,这篇文章我们一起看了一下 AbstractCollectionAbstractList 类,并对相关涉及到的类进行了解析,也是为接下来打好了基础,下篇文章我们将一起来解析一些常用的线性结构具体类 (ArrayListLinkedList)。
如果博客中有什么不正确的地方,还请多多指点。如果这篇文章对您有帮助,请不要吝啬您的赞,欢迎继续关注本专栏。

谢谢观看。。。

猜你喜欢

转载自blog.csdn.net/Hacker_ZhiDian/article/details/80723493