JDK源码分析-Iterator模式

来源:互联网 发布:silverlight mac版本 编辑:程序博客网 时间:2024/06/07 17:33

java.util包中包含了一系列重要的集合类。本文将从分析源码入手,深入研究一个集合类的内部结构,以及遍历集合的迭代模式的源码实现内幕。

下面我们先简单讨论一个根接口Collection,然后分析一个抽象类AbstractList和它的对应Iterator接口,并仔细研究迭代子模式的实现原理。

本文讨论的源代码版本是JDK 1.4.2,因为JDK 1.5在java.util中使用了很多泛型代码,为了简化问题,所以我们还是讨论1.4版本的代码。

集合类的根接口Collection

Collection接口是所有集合类的根类型。它的一个主要的接口方法是:

boolean add(Object c)

add()方法将添加一个新元素。注意这个方法会返回一个boolean,但是返回值不是表示添加成功与否。仔细阅读doc可以看到,Collection规定:如果一个集合拒绝添加这个元素,无论任何原因,都必须抛出异常。这个返回值表示的意义是add()方法执行后,集合的内容是否改变了(就是元素有无数量,位置等变化),这是由具体类实现的。即:如果方法出错,总会抛出异常;返回值仅仅表示该方法执行后这个Collection的内容有无变化。

类似的还有:

boolean addAll(Collection c);boolean remove(Object o);boolean removeAll(Collection c);boolean remainAll(Collection c);

Object[] toArray()方法很简单,把集合转换成数组返回。Object[] toArray(Object[] a)方法就有点复杂了,首先,返回的Object[]仍然是把集合的所有元素变成的数组,但是类型和参数a的类型是相同的,比如执行:

String[] o = (String[])c.toArray(new String[0]);

得到的o实际类型是String[]。

其次,如果参数a的大小装不下集合的所有元素,返回的将是一个新的数组。如果参数a的大小能装下集合的所有元素,则返回的还是a,但a的内容用集合的元素来填充。尤其要注意的是,如果a的大小比集合元素的个数还多,a后面的部分全部被置为null。

最后一个最重要的方法是iterator(),返回一个Iterator(迭代子),用于遍历集合的所有元素。

用Iterator模式实现遍历集合

Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。

例如,如果没有使用Iterator,遍历一个数组的方法是使用索引:

for (int i=0; i<array.size(); i++) {    // TODO: get(i) ...}

而访问一个链表(LinkedList)又必须使用while循环:

while ((e=e.next())!=null) {    // TODO: e.data() ...}

以上两种方法客户端都必须事先知道集合的内部结构,访问代码和集合本身是紧耦合,无法将访问逻辑从集合类和客户端代码中分离出来,每一种集合对应一种遍历方法,客户端代码无法复用。

更恐怖的是,如果以后需要把ArrayList更换为LinkedList,则原来的客户端代码必须全部重写。

为解决以上问题,Iterator模式总是用同一种逻辑来遍历集合:

for (Iterator it = c.iterater(); it.hasNext(); ) { ... }

奥秘在于客户端自身不维护遍历集合的"指针",所有的内部状态(如当前元素位置,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂方法生成,因此,它知道如何遍历整个集合。

客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后","取当前元素"的命令,就可以间接遍历整个集合。

首先看看java.util.Iterator接口的定义:

public interface Iterator {    boolean hasNext();    Object next();    void remove();}

依赖前两个方法就能完成遍历,典型的代码如下:

for (Iterator it = c.iterator(); it.hasNext(); ) {    Object o = it.next();    // 对o的操作...}

在JDK1.5中,还对上面的代码在语法上作了简化:

// Type是具体的类型,如String。for (Type t : c) {    // 对t的操作...}

每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree可能返回TreeIterator,但是它们都实现了Iterator接口,因此,客户端不关心到底是哪种Iterator,它只需要获得这个Iterator接口即可,这就是面向对象的威力。

Iterator源码剖析

让我们来看看AbstracyList如何创建Iterator。首先AbstractList定义了一个内部类(inner class):

private class Itr implements Iterator {    ...}

而iterator()方法的定义是:

public Iterator iterator() {    return new Itr();}

因此客户端不知道它通过Iterator it = a.iterator();所获得的Iterator的真正类型。

现在我们关心的是这个申明为private的Itr类是如何实现遍历AbstractList的:

private class Itr implements Iterator {    int cursor = 0;    int lastRet = -1;    int expectedModCount = modCount;}

Itr类依靠3个int变量(还有一个隐含的AbstractList的引用)来实现遍历,cursor是下一次next()调用时元素的位置,第一次调用next()将返回索引为0的元素。lastRet记录上一次游标所在位置,因此它总是比cursor少1。

变量cursor和集合的元素个数决定hasNext():

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

方法next()返回的是索引为cursor的元素,然后修改cursor和lastRet的值:

public Object next() {    checkForComodification();    try {        Object next = get(cursor);        lastRet = cursor++;        return next;    } catch(IndexOutOfBoundsException e) {        checkForComodification();        throw new NoSuchElementException();    }}

expectedModCount表示期待的modCount值,用来判断在遍历过程中集合是否被修改过。AbstractList包含一个modCount变量,它的初始值是0,当集合每被修改一次时(调用add,remove等方法),modCount加1。因此,modCount如果不变,表示集合内容未被修改。

Itr初始化时用expectedModCount记录集合的modCount变量,此后在必要的地方它会检测modCount的值:

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

如果modCount与一开始记录在expectedModeCount中的值不等,说明集合内容被修改过,此时会抛出ConcurrentModificationException。

这个ConcurrentModificationException是RuntimeException,不要在客户端捕获它。如果发生此异常,说明程序代码的编写有问题,应该仔细检查代码而不是在catch中忽略它。

但是调用Iterator自身的remove()方法删除当前元素是完全没有问题的,因为在这个方法中会自动同步expectedModCount和modCount的值:

public void remove() {    ...    AbstractList.this.remove(lastRet);    ...    // 在调用了集合的remove()方法之后重新设置了expectedModCount:    expectedModCount = modCount;    ...}

要确保遍历过程顺利完成,必须保证遍历过程中不更改集合的内容(Iterator的remove()方法除外),因此,确保遍历可靠的原则是只在一个线程中使用这个集合,或者在多线程中对遍历代码进行同步。

最后给个完整的示例:

Collection c = new ArrayList();c.add("abc");c.add("xyz");for (Iterator it = c.iterator(); it.hasNext(); ) {    String s = (String)it.next();    System.out.println(s);}

如果你把第一行代码的ArrayList换成LinkedList或Vector,剩下的代码不用改动一行就能编译,而且功能不变,这就是针对抽象编程的原则:对具体类的依赖性最小。

廖雪峰 /编程 / 2007-1-11 3:05 / 阅读: 1

本文最早发表于Sun技术社区

http://www.liaoxuefeng.com/article/0013738763641930a85a086bb744d32a81d037f7609b209000


贴心的附上源代码:

/* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.util;import java.util.function.Consumer;/** * An iterator over a collection.  {@code Iterator} takes the place of * {@link Enumeration} in the Java Collections Framework.  Iterators * differ from enumerations in two ways: * * <ul> *      <li> Iterators allow the caller to remove elements from the *           underlying collection during the iteration with well-defined *           semantics. *      <li> Method names have been improved. * </ul> * * <p>This interface is a member of the * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @param <E> the type of elements returned by this iterator * * @author  Josh Bloch * @see Collection * @see ListIterator * @see Iterable * @since 1.2 */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());    }}

/* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.util;import java.util.function.Predicate;import java.util.stream.Stream;import java.util.stream.StreamSupport;/** * The root interface in the <i>collection hierarchy</i>.  A collection * represents a group of objects, known as its <i>elements</i>.  Some * collections allow duplicate elements and others do not.  Some are ordered * and others unordered.  The JDK does not provide any <i>direct</i> * implementations of this interface: it provides implementations of more * specific subinterfaces like <tt>Set</tt> and <tt>List</tt>.  This interface * is typically used to pass collections around and manipulate them where * maximum generality is desired. * * <p><i>Bags</i> or <i>multisets</i> (unordered collections that may contain * duplicate elements) should implement this interface directly. * * <p>All general-purpose <tt>Collection</tt> implementation classes (which * typically implement <tt>Collection</tt> indirectly through one of its * subinterfaces) should provide two "standard" constructors: a void (no * arguments) constructor, which creates an empty collection, and a * constructor with a single argument of type <tt>Collection</tt>, which * creates a new collection with the same elements as its argument.  In * effect, the latter constructor allows the user to copy any collection, * producing an equivalent collection of the desired implementation type. * There is no way to enforce this convention (as interfaces cannot contain * constructors) but all of the general-purpose <tt>Collection</tt> * implementations in the Java platform libraries comply. * * <p>The "destructive" methods contained in this interface, that is, the * methods that modify the collection on which they operate, are specified to * throw <tt>UnsupportedOperationException</tt> if this collection does not * support the operation.  If this is the case, these methods may, but are not * required to, throw an <tt>UnsupportedOperationException</tt> if the * invocation would have no effect on the collection.  For example, invoking * the {@link #addAll(Collection)} method on an unmodifiable collection may, * but is not required to, throw the exception if the collection to be added * is empty. * * <p><a name="optional-restrictions"> * Some collection implementations have restrictions on the elements that * they may contain.</a>  For example, some implementations prohibit null elements, * and some have restrictions on the types of their elements.  Attempting to * add an ineligible element throws an unchecked exception, typically * <tt>NullPointerException</tt> or <tt>ClassCastException</tt>.  Attempting * to query the presence of an ineligible element may throw an exception, * or it may simply return false; some implementations will exhibit the former * behavior and some will exhibit the latter.  More generally, attempting an * operation on an ineligible element whose completion would not result in * the insertion of an ineligible element into the collection may throw an * exception or it may succeed, at the option of the implementation. * Such exceptions are marked as "optional" in the specification for this * interface. * * <p>It is up to each collection to determine its own synchronization * policy.  In the absence of a stronger guarantee by the * implementation, undefined behavior may result from the invocation * of any method on a collection that is being mutated by another * thread; this includes direct invocations, passing the collection to * a method that might perform invocations, and using an existing * iterator to examine the collection. * * <p>Many methods in Collections Framework interfaces are defined in * terms of the {@link Object#equals(Object) equals} method.  For example, * the specification for the {@link #contains(Object) contains(Object o)} * method says: "returns <tt>true</tt> if and only if this collection * contains at least one element <tt>e</tt> such that * <tt>(o==null ? e==null : o.equals(e))</tt>."  This specification should * <i>not</i> be construed to imply that invoking <tt>Collection.contains</tt> * with a non-null argument <tt>o</tt> will cause <tt>o.equals(e)</tt> to be * invoked for any element <tt>e</tt>.  Implementations are free to implement * optimizations whereby the <tt>equals</tt> invocation is avoided, for * example, by first comparing the hash codes of the two elements.  (The * {@link Object#hashCode()} specification guarantees that two objects with * unequal hash codes cannot be equal.)  More generally, implementations of * the various Collections Framework interfaces are free to take advantage of * the specified behavior of underlying {@link Object} methods wherever the * implementor deems it appropriate. * * <p>Some collection operations which perform recursive traversal of the * collection may fail with an exception for self-referential instances where * the collection directly or indirectly contains itself. This includes the * {@code clone()}, {@code equals()}, {@code hashCode()} and {@code toString()} * methods. Implementations may optionally handle the self-referential scenario, * however most current implementations do not do so. * * <p>This interface is a member of the * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @implSpec * The default method implementations (inherited or otherwise) do not apply any * synchronization protocol.  If a {@code Collection} implementation has a * specific synchronization protocol, then it must override default * implementations to apply that protocol. * * @param <E> the type of elements in this collection * * @author  Josh Bloch * @author  Neal Gafter * @see     Set * @see     List * @see     Map * @see     SortedSet * @see     SortedMap * @see     HashSet * @see     TreeSet * @see     ArrayList * @see     LinkedList * @see     Vector * @see     Collections * @see     Arrays * @see     AbstractCollection * @since 1.2 */public interface Collection<E> extends Iterable<E> {    // Query Operations    /**     * Returns the number of elements in this collection.  If this collection     * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns     * <tt>Integer.MAX_VALUE</tt>.     *     * @return the number of elements in this collection     */    int size();    /**     * Returns <tt>true</tt> if this collection contains no elements.     *     * @return <tt>true</tt> if this collection contains no elements     */    boolean isEmpty();    /**     * Returns <tt>true</tt> if this collection contains the specified element.     * More formally, returns <tt>true</tt> if and only if this collection     * contains at least one element <tt>e</tt> such that     * <tt>(o==null ? e==null : o.equals(e))</tt>.     *     * @param o element whose presence in this collection is to be tested     * @return <tt>true</tt> if this collection contains the specified     *         element     * @throws ClassCastException if the type of the specified element     *         is incompatible with this collection     *         (<a href="#optional-restrictions">optional</a>)     * @throws NullPointerException if the specified element is null and this     *         collection does not permit null elements     *         (<a href="#optional-restrictions">optional</a>)     */    boolean contains(Object o);    /**     * Returns an iterator over the elements in this collection.  There are no     * guarantees concerning the order in which the elements are returned     * (unless this collection is an instance of some class that provides a     * guarantee).     *     * @return an <tt>Iterator</tt> over the elements in this collection     */    Iterator<E> iterator();    /**     * Returns an array containing all of the elements in this collection.     * If this collection makes any guarantees as to what order its elements     * are returned by its iterator, this method must return the elements in     * the same order.     *     * <p>The returned array will be "safe" in that no references to it are     * maintained by this collection.  (In other words, this method must     * allocate a new array even if this collection is backed by an 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 collection     */    Object[] toArray();    /**     * Returns an array containing all of the elements in this collection;     * the runtime type of the returned array is that of the specified array.     * If the collection 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 collection.     *     * <p>If this collection fits in the specified array with room to spare     * (i.e., the array has more elements than this collection), 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 this     * collection <i>only</i> if the caller knows that this collection does     * not contain any <tt>null</tt> elements.)     *     * <p>If this collection makes any guarantees as to what order its elements     * are returned by its iterator, this method must return the elements in     * the same order.     *     * <p>Like the {@link #toArray()} method, this method acts as bridge between     * array-based and collection-based APIs.  Further, this method allows     * precise control over the runtime type of the output array, and may,     * under certain circumstances, be used to save allocation costs.     *     * <p>Suppose <tt>x</tt> is a collection known to contain only strings.     * The following code can be used to dump the collection into a newly     * allocated array of <tt>String</tt>:     *     * <pre>     *     String[] y = x.toArray(new String[0]);</pre>     *     * Note that <tt>toArray(new Object[0])</tt> is identical in function to     * <tt>toArray()</tt>.     *     * @param <T> the runtime type of the array to contain the collection     * @param a the array into which the elements of this collection 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 all of the elements in this collection     * @throws ArrayStoreException if the runtime type of the specified array     *         is not a supertype of the runtime type of every element in     *         this collection     * @throws NullPointerException if the specified array is null     */    <T> T[] toArray(T[] a);    // Modification Operations    /**     * Ensures that this collection contains the specified element (optional     * operation).  Returns <tt>true</tt> if this collection changed as a     * result of the call.  (Returns <tt>false</tt> if this collection does     * not permit duplicates and already contains the specified element.)<p>     *     * Collections that support this operation may place limitations on what     * elements may be added to this collection.  In particular, some     * collections will refuse to add <tt>null</tt> elements, and others will     * impose restrictions on the type of elements that may be added.     * Collection classes should clearly specify in their documentation any     * restrictions on what elements may be added.<p>     *     * If a collection refuses to add a particular element for any reason     * other than that it already contains the element, it <i>must</i> throw     * an exception (rather than returning <tt>false</tt>).  This preserves     * the invariant that a collection always contains the specified element     * after this call returns.     *     * @param e element whose presence in this collection is to be ensured     * @return <tt>true</tt> if this collection changed as a result of the     *         call     * @throws UnsupportedOperationException if the <tt>add</tt> operation     *         is not supported by this collection     * @throws ClassCastException if the class of the specified element     *         prevents it from being added to this collection     * @throws NullPointerException if the specified element is null and this     *         collection does not permit null elements     * @throws IllegalArgumentException if some property of the element     *         prevents it from being added to this collection     * @throws IllegalStateException if the element cannot be added at this     *         time due to insertion restrictions     */    boolean add(E e);    /**     * Removes a single instance of the specified element from this     * collection, if it is present (optional operation).  More formally,     * removes an element <tt>e</tt> such that     * <tt>(o==null ? e==null : o.equals(e))</tt>, if     * this collection contains one or more such elements.  Returns     * <tt>true</tt> if this collection contained the specified element (or     * equivalently, if this collection changed as a result of the call).     *     * @param o element to be removed from this collection, if present     * @return <tt>true</tt> if an element was removed as a result of this call     * @throws ClassCastException if the type of the specified element     *         is incompatible with this collection     *         (<a href="#optional-restrictions">optional</a>)     * @throws NullPointerException if the specified element is null and this     *         collection does not permit null elements     *         (<a href="#optional-restrictions">optional</a>)     * @throws UnsupportedOperationException if the <tt>remove</tt> operation     *         is not supported by this collection     */    boolean remove(Object o);    // Bulk Operations    /**     * Returns <tt>true</tt> if this collection contains all of the elements     * in the specified collection.     *     * @param  c collection to be checked for containment in this collection     * @return <tt>true</tt> if this collection contains all of the elements     *         in the specified collection     * @throws ClassCastException if the types of one or more elements     *         in the specified collection are incompatible with this     *         collection     *         (<a href="#optional-restrictions">optional</a>)     * @throws NullPointerException if the specified collection contains one     *         or more null elements and this collection does not permit null     *         elements     *         (<a href="#optional-restrictions">optional</a>),     *         or if the specified collection is null.     * @see    #contains(Object)     */    boolean containsAll(Collection<?> c);    /**     * Adds all of the elements in the specified collection to this collection     * (optional operation).  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 collection, and this collection is     * nonempty.)     *     * @param c collection containing elements to be added to this collection     * @return <tt>true</tt> if this collection changed as a result of the call     * @throws UnsupportedOperationException if the <tt>addAll</tt> operation     *         is not supported by this collection     * @throws ClassCastException if the class of an element of the specified     *         collection prevents it from being added to this collection     * @throws NullPointerException if the specified collection contains a     *         null element and this collection does not permit null elements,     *         or if the specified collection is null     * @throws IllegalArgumentException if some property of an element of the     *         specified collection prevents it from being added to this     *         collection     * @throws IllegalStateException if not all the elements can be added at     *         this time due to insertion restrictions     * @see #add(Object)     */    boolean addAll(Collection<? extends E> c);    /**     * Removes all of this collection's elements that are also contained in the     * specified collection (optional operation).  After this call returns,     * this collection will contain no elements in common with the specified     * collection.     *     * @param c collection containing elements to be removed from this collection     * @return <tt>true</tt> if this collection changed as a result of the     *         call     * @throws UnsupportedOperationException if the <tt>removeAll</tt> method     *         is not supported by this collection     * @throws ClassCastException if the types of one or more elements     *         in this collection are incompatible with the specified     *         collection     *         (<a href="#optional-restrictions">optional</a>)     * @throws NullPointerException if this collection contains one or more     *         null elements and the specified collection does not support     *         null elements     *         (<a href="#optional-restrictions">optional</a>),     *         or if the specified collection is null     * @see #remove(Object)     * @see #contains(Object)     */    boolean removeAll(Collection<?> c);    /**     * Removes all of the elements of this collection that satisfy the given     * predicate.  Errors or runtime exceptions thrown during iteration or by     * the predicate are relayed to the caller.     *     * @implSpec     * The default implementation traverses all elements of the collection using     * its {@link #iterator}.  Each matching element is removed using     * {@link Iterator#remove()}.  If the collection's iterator does not     * support removal then an {@code UnsupportedOperationException} will be     * thrown on the first matching element.     *     * @param filter a predicate which returns {@code true} for elements to be     *        removed     * @return {@code true} if any elements were removed     * @throws NullPointerException if the specified filter is null     * @throws UnsupportedOperationException if elements cannot be removed     *         from this collection.  Implementations may throw this exception if a     *         matching element cannot be removed or if, in general, removal is not     *         supported.     * @since 1.8     */    default boolean removeIf(Predicate<? super E> filter) {        Objects.requireNonNull(filter);        boolean removed = false;        final Iterator<E> each = iterator();        while (each.hasNext()) {            if (filter.test(each.next())) {                each.remove();                removed = true;            }        }        return removed;    }    /**     * Retains only the elements in this collection that are contained in the     * specified collection (optional operation).  In other words, removes from     * this collection all of its elements that are not contained in the     * specified collection.     *     * @param c collection containing elements to be retained in this collection     * @return <tt>true</tt> if this collection changed as a result of the call     * @throws UnsupportedOperationException if the <tt>retainAll</tt> operation     *         is not supported by this collection     * @throws ClassCastException if the types of one or more elements     *         in this collection are incompatible with the specified     *         collection     *         (<a href="#optional-restrictions">optional</a>)     * @throws NullPointerException if this collection contains one or more     *         null elements and the specified collection does not permit null     *         elements     *         (<a href="#optional-restrictions">optional</a>),     *         or if the specified collection is null     * @see #remove(Object)     * @see #contains(Object)     */    boolean retainAll(Collection<?> c);    /**     * Removes all of the elements from this collection (optional operation).     * The collection will be empty after this method returns.     *     * @throws UnsupportedOperationException if the <tt>clear</tt> operation     *         is not supported by this collection     */    void clear();    // Comparison and hashing    /**     * Compares the specified object with this collection for equality. <p>     *     * While the <tt>Collection</tt> interface adds no stipulations to the     * general contract for the <tt>Object.equals</tt>, programmers who     * implement the <tt>Collection</tt> interface "directly" (in other words,     * create a class that is a <tt>Collection</tt> but is not a <tt>Set</tt>     * or a <tt>List</tt>) must exercise care if they choose to override the     * <tt>Object.equals</tt>.  It is not necessary to do so, and the simplest     * course of action is to rely on <tt>Object</tt>'s implementation, but     * the implementor may wish to implement a "value comparison" in place of     * the default "reference comparison."  (The <tt>List</tt> and     * <tt>Set</tt> interfaces mandate such value comparisons.)<p>     *     * The general contract for the <tt>Object.equals</tt> method states that     * equals must be symmetric (in other words, <tt>a.equals(b)</tt> if and     * only if <tt>b.equals(a)</tt>).  The contracts for <tt>List.equals</tt>     * and <tt>Set.equals</tt> state that lists are only equal to other lists,     * and sets to other sets.  Thus, a custom <tt>equals</tt> method for a     * collection class that implements neither the <tt>List</tt> nor     * <tt>Set</tt> interface must return <tt>false</tt> when this collection     * is compared to any list or set.  (By the same logic, it is not possible     * to write a class that correctly implements both the <tt>Set</tt> and     * <tt>List</tt> interfaces.)     *     * @param o object to be compared for equality with this collection     * @return <tt>true</tt> if the specified object is equal to this     * collection     *     * @see Object#equals(Object)     * @see Set#equals(Object)     * @see List#equals(Object)     */    boolean equals(Object o);    /**     * Returns the hash code value for this collection.  While the     * <tt>Collection</tt> interface adds no stipulations to the general     * contract for the <tt>Object.hashCode</tt> method, programmers should     * take note that any class that overrides the <tt>Object.equals</tt>     * method must also override the <tt>Object.hashCode</tt> method in order     * to satisfy the general contract for the <tt>Object.hashCode</tt> method.     * In particular, <tt>c1.equals(c2)</tt> implies that     * <tt>c1.hashCode()==c2.hashCode()</tt>.     *     * @return the hash code value for this collection     *     * @see Object#hashCode()     * @see Object#equals(Object)     */    int hashCode();    /**     * Creates a {@link Spliterator} over the elements in this collection.     *     * Implementations should document characteristic values reported by the     * spliterator.  Such characteristic values are not required to be reported     * if the spliterator reports {@link Spliterator#SIZED} and this collection     * contains no elements.     *     * <p>The default implementation should be overridden by subclasses that     * can return a more efficient spliterator.  In order to     * preserve expected laziness behavior for the {@link #stream()} and     * {@link #parallelStream()}} methods, spliterators should either have the     * characteristic of {@code IMMUTABLE} or {@code CONCURRENT}, or be     * <em><a href="Spliterator.html#binding">late-binding</a></em>.     * If none of these is practical, the overriding class should describe the     * spliterator's documented policy of binding and structural interference,     * and should override the {@link #stream()} and {@link #parallelStream()}     * methods to create streams using a {@code Supplier} of the spliterator,     * as in:     * <pre>{@code     *     Stream<E> s = StreamSupport.stream(() -> spliterator(), spliteratorCharacteristics)     * }</pre>     * <p>These requirements ensure that streams produced by the     * {@link #stream()} and {@link #parallelStream()} methods will reflect the     * contents of the collection as of initiation of the terminal stream     * operation.     *     * @implSpec     * The default implementation creates a     * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator     * from the collections's {@code Iterator}.  The spliterator inherits the     * <em>fail-fast</em> properties of the collection's iterator.     * <p>     * The created {@code Spliterator} reports {@link Spliterator#SIZED}.     *     * @implNote     * The created {@code Spliterator} additionally reports     * {@link Spliterator#SUBSIZED}.     *     * <p>If a spliterator covers no elements then the reporting of additional     * characteristic values, beyond that of {@code SIZED} and {@code SUBSIZED},     * does not aid clients to control, specialize or simplify computation.     * However, this does enable shared use of an immutable and empty     * spliterator instance (see {@link Spliterators#emptySpliterator()}) for     * empty collections, and enables clients to determine if such a spliterator     * covers no elements.     *     * @return a {@code Spliterator} over the elements in this collection     * @since 1.8     */    @Override    default Spliterator<E> spliterator() {        return Spliterators.spliterator(this, 0);    }    /**     * Returns a sequential {@code Stream} with this collection as its source.     *     * <p>This method should be overridden when the {@link #spliterator()}     * method cannot return a spliterator that is {@code IMMUTABLE},     * {@code CONCURRENT}, or <em>late-binding</em>. (See {@link #spliterator()}     * for details.)     *     * @implSpec     * The default implementation creates a sequential {@code Stream} from the     * collection's {@code Spliterator}.     *     * @return a sequential {@code Stream} over the elements in this collection     * @since 1.8     */    default Stream<E> stream() {        return StreamSupport.stream(spliterator(), false);    }    /**     * Returns a possibly parallel {@code Stream} with this collection as its     * source.  It is allowable for this method to return a sequential stream.     *     * <p>This method should be overridden when the {@link #spliterator()}     * method cannot return a spliterator that is {@code IMMUTABLE},     * {@code CONCURRENT}, or <em>late-binding</em>. (See {@link #spliterator()}     * for details.)     *     * @implSpec     * The default implementation creates a parallel {@code Stream} from the     * collection's {@code Spliterator}.     *     * @return a possibly parallel {@code Stream} over the elements in this     * collection     * @since 1.8     */    default Stream<E> parallelStream() {        return StreamSupport.stream(spliterator(), true);    }}

/* * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.util;/** * This class provides a skeletal implementation of the {@link 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), {@link AbstractSequentialList} should * be used in preference to this class. * * <p>To implement an unmodifiable list, the programmer needs only to extend * this class and provide implementations for the {@link #get(int)} and * {@link List#size() size()} methods. * * <p>To implement a modifiable list, the programmer must additionally * override the {@link #set(int, Object) set(int, E)} method (which otherwise * throws an {@code UnsupportedOperationException}).  If the list is * variable-size the programmer must additionally override the * {@link #add(int, Object) add(int, E)} and {@link #remove(int)} methods. * * <p>The programmer should generally provide a void (no argument) and collection * constructor, as per the recommendation in the {@link Collection} interface * specification. * * <p>Unlike the other abstract collection implementations, the programmer does * <i>not</i> have to provide an iterator implementation; the iterator and * list iterator are implemented by this class, on top of the "random access" * methods: * {@link #get(int)}, * {@link #set(int, Object) set(int, E)}, * {@link #add(int, Object) add(int, E)} and * {@link #remove(int)}. * * <p>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. * * <p>This class is a member of the * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author  Josh Bloch * @author  Neal Gafter * @since 1.2 */public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {    /**     * Sole constructor.  (For invocation by subclass constructors, typically     * implicit.)     */    protected AbstractList() {    }    /**     * Appends the specified element to the end of this list (optional     * operation).     *     * <p>Lists that support this operation may place limitations on what     * elements may be added to this list.  In particular, some     * lists will refuse to add null elements, and others will impose     * restrictions on the type of elements that may be added.  List     * classes should clearly specify in their documentation any restrictions     * on what elements may be added.     *     * <p>This implementation calls {@code add(size(), e)}.     *     * <p>Note that this implementation throws an     * {@code UnsupportedOperationException} unless     * {@link #add(int, Object) add(int, E)} is overridden.     *     * @param e element to be appended to this list     * @return {@code true} (as specified by {@link Collection#add})     * @throws UnsupportedOperationException if the {@code add} operation     *         is not supported by this list     * @throws ClassCastException if the class of the specified element     *         prevents it from being added to this list     * @throws NullPointerException if the specified element is null and this     *         list does not permit null elements     * @throws IllegalArgumentException if some property of this element     *         prevents it from being added to this list     */    public boolean add(E e) {        add(size(), e);        return true;    }    /**     * {@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;    }    // Bulk Operations    /**     * Removes all of the elements from this list (optional operation).     * The list will be empty after this call returns.     *     * <p>This implementation calls {@code removeRange(0, size())}.     *     * <p>Note that this implementation throws an     * {@code UnsupportedOperationException} unless {@code remove(int     * index)} or {@code removeRange(int fromIndex, int toIndex)} is     * overridden.     *     * @throws UnsupportedOperationException if the {@code clear} operation     *         is not supported by this list     */    public void clear() {        removeRange(0, size());    }    /**     * {@inheritDoc}     *     * <p>This implementation gets an iterator over the specified collection     * and iterates over it, inserting the elements obtained from the     * iterator into this list at the appropriate position, one at a time,     * using {@code add(int, E)}.     * Many implementations will override this method for efficiency.     *     * <p>Note that this implementation throws an     * {@code UnsupportedOperationException} unless     * {@link #add(int, Object) add(int, E)} is overridden.     *     * @throws UnsupportedOperationException {@inheritDoc}     * @throws ClassCastException            {@inheritDoc}     * @throws NullPointerException          {@inheritDoc}     * @throws IllegalArgumentException      {@inheritDoc}     * @throws IndexOutOfBoundsException     {@inheritDoc}     */    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    /**     * Returns an iterator over the elements in this list in proper sequence.     *     * <p>This implementation returns a straightforward implementation of the     * iterator interface, relying on the backing list's {@code size()},     * {@code get(int)}, and {@code remove(int)} methods.     *     * <p>Note that the iterator returned by this method will throw an     * {@link UnsupportedOperationException} in response to its     * {@code remove} method unless the list's {@code remove(int)} method is     * overridden.     *     * <p>This implementation can be made to throw runtime exceptions in the     * face of concurrent modification, as described in the specification     * for the (protected) {@link #modCount} field.     *     * @return an iterator over the elements in this list in proper sequence     */    public Iterator<E> iterator() {        return new Itr();    }    /**     * {@inheritDoc}     *     * <p>This implementation returns {@code listIterator(0)}.     *     * @see #listIterator(int)     */    public ListIterator<E> listIterator() {        return listIterator(0);    }    /**     * {@inheritDoc}     *     * <p>This implementation returns a straightforward implementation of the     * {@code ListIterator} interface that extends the implementation of the     * {@code Iterator} interface returned by the {@code iterator()} method.     * The {@code ListIterator} implementation relies on the backing list's     * {@code get(int)}, {@code set(int, E)}, {@code add(int, E)}     * and {@code remove(int)} methods.     *     * <p>Note that the list iterator returned by this implementation will     * throw an {@link UnsupportedOperationException} in response to its     * {@code remove}, {@code set} and {@code add} methods unless the     * list's {@code remove(int)}, {@code set(int, E)}, and     * {@code add(int, E)} methods are overridden.     *     * <p>This implementation can be made to throw runtime exceptions in the     * face of concurrent modification, as described in the specification for     * the (protected) {@link #modCount} field.     *     * @throws IndexOutOfBoundsException {@inheritDoc}     */    public ListIterator<E> listIterator(final int index) {        rangeCheckForAdd(index);        return new ListItr(index);    }    private class Itr implements Iterator<E> {        /**         * Index of element to be returned by subsequent call to next.         */        int cursor = 0;        /**         * Index of element returned by most recent call to next or         * previous.  Reset to -1 if this element is deleted by a call         * to remove.         */        int lastRet = -1;        /**         * The modCount value that the iterator believes that the backing         * List should have.  If this expectation is violated, the iterator         * has detected concurrent modification.         */        int expectedModCount = modCount;        public boolean hasNext() {            return cursor != size();        }        public E next() {            checkForComodification();            try {                int i = cursor;                E next = get(i);                lastRet = i;                cursor = i + 1;                return next;            } catch (IndexOutOfBoundsException e) {                checkForComodification();                throw new NoSuchElementException();            }        }        public void remove() {            if (lastRet < 0)                throw new IllegalStateException();            checkForComodification();            try {                AbstractList.this.remove(lastRet);                if (lastRet < cursor)                    cursor--;                lastRet = -1;                expectedModCount = modCount;            } catch (IndexOutOfBoundsException e) {                throw new ConcurrentModificationException();            }        }        final void checkForComodification() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();        }    }    private class ListItr extends Itr implements ListIterator<E> {        ListItr(int index) {            cursor = index;        }        public boolean hasPrevious() {            return cursor != 0;        }        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();            }        }        public int nextIndex() {            return cursor;        }        public int previousIndex() {            return cursor-1;        }        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();            }        }        public void add(E e) {            checkForComodification();            try {                int i = cursor;                AbstractList.this.add(i, e);                lastRet = -1;                cursor = i + 1;                expectedModCount = modCount;            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }    }    /**     * {@inheritDoc}     *     * <p>This implementation returns a list that subclasses     * {@code AbstractList}.  The subclass stores, in private fields, the     * offset of the subList within the backing list, the size of the subList     * (which can change over its lifetime), and the expected     * {@code modCount} value of the backing list.  There are two variants     * of the subclass, one of which implements {@code RandomAccess}.     * If this list implements {@code RandomAccess} the returned list will     * be an instance of the subclass that implements {@code RandomAccess}.     *     * <p>The subclass's {@code set(int, E)}, {@code get(int)},     * {@code add(int, E)}, {@code remove(int)}, {@code addAll(int,     * Collection)} and {@code removeRange(int, int)} methods all     * delegate to the corresponding methods on the backing abstract list,     * after bounds-checking the index and adjusting for the offset.  The     * {@code addAll(Collection c)} method merely returns {@code addAll(size,     * c)}.     *     * <p>The {@code listIterator(int)} method returns a "wrapper object"     * over a list iterator on the backing list, which is created with the     * corresponding method on the backing list.  The {@code iterator} method     * merely returns {@code listIterator()}, and the {@code size} method     * merely returns the subclass's {@code size} field.     *     * <p>All methods first check to see if the actual {@code modCount} of     * the backing list is equal to its expected value, and throw a     * {@code ConcurrentModificationException} if it is not.     *     * @throws IndexOutOfBoundsException if an endpoint index value is out of range     *         {@code (fromIndex < 0 || toIndex > size)}     * @throws IllegalArgumentException if the endpoint indices are out of order     *         {@code (fromIndex > toIndex)}     */    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    /**     * 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;        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());    }    /**     * Returns the hash code value for this list.     *     * <p>This implementation uses exactly the code that is used to define the     * list hash function in the documentation for the {@link List#hashCode}     * method.     *     * @return the hash code value for this list     */    public int hashCode() {        int hashCode = 1;        for (E e : this)            hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());        return hashCode;    }    /**     * 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.)     *     * <p>This method is called by the {@code clear} operation on this list     * and its subLists.  Overriding this method to take advantage of     * the internals of the list implementation can <i>substantially</i>     * improve the performance of the {@code clear} operation on this list     * and its subLists.     *     * <p>This implementation gets a list iterator positioned before     * {@code fromIndex}, and repeatedly calls {@code ListIterator.next}     * followed by {@code ListIterator.remove} until the entire range has     * been removed.  <b>Note: if {@code ListIterator.remove} requires linear     * time, this implementation requires quadratic time.</b>     *     * @param fromIndex index of first element to be removed     * @param toIndex index after last element to be removed     */    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();        }    }    /**     * 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.     */    protected transient int modCount = 0;    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();    }}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();        return l.set(index+offset, element);    }    public E get(int index) {        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();    }    public ListIterator<E> listIterator(final int index) {        checkForComodification();        rangeCheckForAdd(index);        return new ListIterator<E>() {            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();    }}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);    }}


廖雪峰 /编程 / 2007-1-11 3:05 / 阅读: 1

本文最早发表于Sun技术社区

0 0
原创粉丝点击