View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections.list;
18  
19  import java.io.IOException;
20  import java.io.ObjectInputStream;
21  import java.io.ObjectOutputStream;
22  import java.lang.reflect.Array;
23  import java.util.AbstractList;
24  import java.util.Collection;
25  import java.util.ConcurrentModificationException;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.ListIterator;
29  import java.util.NoSuchElementException;
30  
31  import org.apache.commons.collections.OrderedIterator;
32  
33  /**
34   * An abstract implementation of a linked list which provides numerous points for
35   * subclasses to override.
36   * <p>
37   * Overridable methods are provided to change the storage node and to change how
38   * nodes are added to and removed. Hopefully, all you need for unusual subclasses
39   * is here.
40   *
41   * @since 3.0
42   * @version $Id: AbstractLinkedList.java 1443602 2013-02-07 17:00:23Z tn $
43   */
44  public abstract class AbstractLinkedList<E> implements List<E> {
45  
46      /*
47       * Implementation notes:
48       * - a standard circular doubly-linked list
49       * - a marker node is stored to mark the start and the end of the list
50       * - node creation and removal always occurs through createNode() and
51       *   removeNode().
52       * - a modification count is kept, with the same semantics as
53       * {@link java.util.LinkedList}.
54       * - respects {@link AbstractList#modCount}
55       */
56  
57      /**
58       * A {@link Node} which indicates the start and end of the list and does not
59       * hold a value. The value of <code>next</code> is the first item in the
60       * list. The value of of <code>previous</code> is the last item in the list.
61       */
62      protected transient Node<E> header;
63  
64      /** The size of the list */
65      protected transient int size;
66  
67      /** Modification count for iterators */
68      protected transient int modCount;
69  
70      /**
71       * Constructor that does nothing intended for deserialization.
72       * <p>
73       * If this constructor is used by a serializable subclass then the init()
74       * method must be called.
75       */
76      protected AbstractLinkedList() {
77          super();
78      }
79  
80      /**
81       * Constructs a list copying data from the specified collection.
82       *
83       * @param coll  the collection to copy
84       */
85      protected AbstractLinkedList(final Collection<? extends E> coll) {
86          super();
87          init();
88          addAll(coll);
89      }
90  
91      /**
92       * The equivalent of a default constructor, broken out so it can be called
93       * by any constructor and by <code>readObject</code>.
94       * Subclasses which override this method should make sure they call super,
95       * so the list is initialised properly.
96       */
97      protected void init() {
98          header = createHeaderNode();
99      }
100 
101     //-----------------------------------------------------------------------
102     
103     public int size() {
104         return size;
105     }
106 
107     public boolean isEmpty() {
108         return size() == 0;
109     }
110 
111     public E get(final int index) {
112         final Node<E> node = getNode(index, false);
113         return node.getValue();
114     }
115 
116     //-----------------------------------------------------------------------
117     
118     public Iterator<E> iterator() {
119         return listIterator();
120     }
121 
122     public ListIterator<E> listIterator() {
123         return new LinkedListIterator<E>(this, 0);
124     }
125 
126     public ListIterator<E> listIterator(final int fromIndex) {
127         return new LinkedListIterator<E>(this, fromIndex);
128     }
129 
130     //-----------------------------------------------------------------------
131     
132     public int indexOf(final Object value) {
133         int i = 0;
134         for (Node<E> node = header.next; node != header; node = node.next) {
135             if (isEqualValue(node.getValue(), value)) {
136                 return i;
137             }
138             i++;
139         }
140         return -1;
141     }
142 
143     public int lastIndexOf(final Object value) {
144         int i = size - 1;
145         for (Node<E> node = header.previous; node != header; node = node.previous) {
146             if (isEqualValue(node.getValue(), value)) {
147                 return i;
148             }
149             i--;
150         }
151         return -1;
152     }
153 
154     public boolean contains(final Object value) {
155         return indexOf(value) != -1;
156     }
157 
158     public boolean containsAll(final Collection<?> coll) {
159         for (final Object o : coll) {
160             if (!contains(o)) {
161                 return false;
162             }
163         }
164         return true;
165     }
166 
167     //-----------------------------------------------------------------------
168     
169     public Object[] toArray() {
170         return toArray(new Object[size]);
171     }
172 
173     @SuppressWarnings("unchecked")
174     public <T> T[] toArray(T[] array) {
175         // Extend the array if needed
176         if (array.length < size) {
177             final Class<?> componentType = array.getClass().getComponentType();
178             array = (T[]) Array.newInstance(componentType, size);
179         }
180         // Copy the values into the array
181         int i = 0;
182         for (Node<E> node = header.next; node != header; node = node.next, i++) {
183             array[i] = (T) node.getValue();
184         }
185         // Set the value after the last value to null
186         if (array.length > size) {
187             array[size] = null;
188         }
189         return array;
190     }
191 
192     /**
193      * Gets a sublist of the main list.
194      *
195      * @param fromIndexInclusive  the index to start from
196      * @param toIndexExclusive  the index to end at
197      * @return the new sublist
198      */
199     public List<E> subList(final int fromIndexInclusive, final int toIndexExclusive) {
200         return new LinkedSubList<E>(this, fromIndexInclusive, toIndexExclusive);
201     }
202 
203     //-----------------------------------------------------------------------
204     
205     public boolean add(final E value) {
206         addLast(value);
207         return true;
208     }
209 
210     public void add(final int index, final E value) {
211         final Node<E> node = getNode(index, true);
212         addNodeBefore(node, value);
213     }
214 
215     public boolean addAll(final Collection<? extends E> coll) {
216         return addAll(size, coll);
217     }
218 
219     public boolean addAll(final int index, final Collection<? extends E> coll) {
220         final Node<E> node = getNode(index, true);
221         for (final E e : coll) {
222             addNodeBefore(node, e);
223         }
224         return true;
225     }
226 
227     //-----------------------------------------------------------------------
228     
229     public E remove(final int index) {
230         final Node<E> node = getNode(index, false);
231         final E oldValue = node.getValue();
232         removeNode(node);
233         return oldValue;
234     }
235 
236     public boolean remove(final Object value) {
237         for (Node<E> node = header.next; node != header; node = node.next) {
238             if (isEqualValue(node.getValue(), value)) {
239                 removeNode(node);
240                 return true;
241             }
242         }
243         return false;
244     }
245 
246     /**
247      * {@inheritDoc}
248      * <p> 
249      * This implementation iterates over the elements of this list, checking each element in
250      * turn to see if it's contained in <code>coll</code>. If it's contained, it's removed
251      * from this list. As a consequence, it is advised to use a collection type for
252      * <code>coll</code> that provides a fast (e.g. O(1)) implementation of
253      * {@link Collection#contains(Object)}.
254      */
255     public boolean removeAll(final Collection<?> coll) {
256         boolean modified = false;
257         final Iterator<E> it = iterator();
258         while (it.hasNext()) {
259             if (coll.contains(it.next())) {
260                 it.remove();
261                 modified = true;
262             }
263         }
264         return modified;
265     }
266 
267     //-----------------------------------------------------------------------
268     
269     /**
270      * {@inheritDoc}
271      * <p> 
272      * This implementation iterates over the elements of this list, checking each element in
273      * turn to see if it's contained in <code>coll</code>. If it's not contained, it's removed
274      * from this list. As a consequence, it is advised to use a collection type for
275      * <code>coll</code> that provides a fast (e.g. O(1)) implementation of
276      * {@link Collection#contains(Object)}.
277      */
278     public boolean retainAll(final Collection<?> coll) {
279         boolean modified = false;
280         final Iterator<E> it = iterator();
281         while (it.hasNext()) {
282             if (coll.contains(it.next()) == false) {
283                 it.remove();
284                 modified = true;
285             }
286         }
287         return modified;
288     }
289 
290     public E set(final int index, final E value) {
291         final Node<E> node = getNode(index, false);
292         final E oldValue = node.getValue();
293         updateNode(node, value);
294         return oldValue;
295     }
296 
297     public void clear() {
298         removeAllNodes();
299     }
300 
301     //-----------------------------------------------------------------------
302     
303     public E getFirst() {
304         final Node<E> node = header.next;
305         if (node == header) {
306             throw new NoSuchElementException();
307         }
308         return node.getValue();
309     }
310 
311     public E getLast() {
312         final Node<E> node = header.previous;
313         if (node == header) {
314             throw new NoSuchElementException();
315         }
316         return node.getValue();
317     }
318 
319     public boolean addFirst(final E o) {
320         addNodeAfter(header, o);
321         return true;
322     }
323 
324     public boolean addLast(final E o) {
325         addNodeBefore(header, o);
326         return true;
327     }
328 
329     public E removeFirst() {
330         final Node<E> node = header.next;
331         if (node == header) {
332             throw new NoSuchElementException();
333         }
334         final E oldValue = node.getValue();
335         removeNode(node);
336         return oldValue;
337     }
338 
339     public E removeLast() {
340         final Node<E> node = header.previous;
341         if (node == header) {
342             throw new NoSuchElementException();
343         }
344         final E oldValue = node.getValue();
345         removeNode(node);
346         return oldValue;
347     }
348 
349     //-----------------------------------------------------------------------
350     @Override
351     public boolean equals(final Object obj) {
352         if (obj == this) {
353             return true;
354         }
355         if (obj instanceof List == false) {
356             return false;
357         }
358         final List<?> other = (List<?>) obj;
359         if (other.size() != size()) {
360             return false;
361         }
362         final ListIterator<?> it1 = listIterator();
363         final ListIterator<?> it2 = other.listIterator();
364         while (it1.hasNext() && it2.hasNext()) {
365             final Object o1 = it1.next();
366             final Object o2 = it2.next();
367             if (!(o1 == null ? o2 == null : o1.equals(o2))) {
368                 return false;
369             }
370         }
371         return !(it1.hasNext() || it2.hasNext());
372     }
373 
374     @Override
375     public int hashCode() {
376         int hashCode = 1;
377         for (final E e : this) {
378             hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
379         }
380         return hashCode;
381     }
382 
383     @Override
384     public String toString() {
385         if (size() == 0) {
386             return "[]";
387         }
388         final StringBuilder buf = new StringBuilder(16 * size());
389         buf.append('[');
390 
391         final Iterator<E> it = iterator();
392         boolean hasNext = it.hasNext();
393         while (hasNext) {
394             final Object value = it.next();
395             buf.append(value == this ? "(this Collection)" : value);
396             hasNext = it.hasNext();
397             if (hasNext) {
398                 buf.append(", ");
399             }
400         }
401         buf.append(']');
402         return buf.toString();
403     }
404 
405     //-----------------------------------------------------------------------
406     /**
407      * Compares two values for equals.
408      * This implementation uses the equals method.
409      * Subclasses can override this to match differently.
410      *
411      * @param value1  the first value to compare, may be null
412      * @param value2  the second value to compare, may be null
413      * @return true if equal
414      */
415     protected boolean isEqualValue(final Object value1, final Object value2) {
416         return value1 == value2 || (value1 == null ? false : value1.equals(value2));
417     }
418 
419     /**
420      * Updates the node with a new value.
421      * This implementation sets the value on the node.
422      * Subclasses can override this to record the change.
423      *
424      * @param node  node to update
425      * @param value  new value of the node
426      */
427     protected void updateNode(final Node<E> node, final E value) {
428         node.setValue(value);
429     }
430 
431     /**
432      * Creates a new node with previous, next and element all set to null.
433      * This implementation creates a new empty Node.
434      * Subclasses can override this to create a different class.
435      *
436      * @return  newly created node
437      */
438     protected Node<E> createHeaderNode() {
439         return new Node<E>();
440     }
441 
442     /**
443      * Creates a new node with the specified properties.
444      * This implementation creates a new Node with data.
445      * Subclasses can override this to create a different class.
446      *
447      * @param value  value of the new node
448      * @return a new node containing the value
449      */
450     protected Node<E> createNode(final E value) {
451         return new Node<E>(value);
452     }
453 
454     /**
455      * Creates a new node with the specified object as its
456      * <code>value</code> and inserts it before <code>node</code>.
457      * <p>
458      * This implementation uses {@link #createNode(Object)} and
459      * {@link #addNode(AbstractLinkedList.Node,AbstractLinkedList.Node)}.
460      *
461      * @param node  node to insert before
462      * @param value  value of the newly added node
463      * @throws NullPointerException if <code>node</code> is null
464      */
465     protected void addNodeBefore(final Node<E> node, final E value) {
466         final Node<E> newNode = createNode(value);
467         addNode(newNode, node);
468     }
469 
470     /**
471      * Creates a new node with the specified object as its
472      * <code>value</code> and inserts it after <code>node</code>.
473      * <p>
474      * This implementation uses {@link #createNode(Object)} and
475      * {@link #addNode(AbstractLinkedList.Node,AbstractLinkedList.Node)}.
476      *
477      * @param node  node to insert after
478      * @param value  value of the newly added node
479      * @throws NullPointerException if <code>node</code> is null
480      */
481     protected void addNodeAfter(final Node<E> node, final E value) {
482         final Node<E> newNode = createNode(value);
483         addNode(newNode, node.next);
484     }
485 
486     /**
487      * Inserts a new node into the list.
488      *
489      * @param nodeToInsert  new node to insert
490      * @param insertBeforeNode  node to insert before
491      * @throws NullPointerException if either node is null
492      */
493     protected void addNode(final Node<E> nodeToInsert, final Node<E> insertBeforeNode) {
494         nodeToInsert.next = insertBeforeNode;
495         nodeToInsert.previous = insertBeforeNode.previous;
496         insertBeforeNode.previous.next = nodeToInsert;
497         insertBeforeNode.previous = nodeToInsert;
498         size++;
499         modCount++;
500     }
501 
502     /**
503      * Removes the specified node from the list.
504      *
505      * @param node  the node to remove
506      * @throws NullPointerException if <code>node</code> is null
507      */
508     protected void removeNode(final Node<E> node) {
509         node.previous.next = node.next;
510         node.next.previous = node.previous;
511         size--;
512         modCount++;
513     }
514 
515     /**
516      * Removes all nodes by resetting the circular list marker.
517      */
518     protected void removeAllNodes() {
519         header.next = header;
520         header.previous = header;
521         size = 0;
522         modCount++;
523     }
524 
525     /**
526      * Gets the node at a particular index.
527      *
528      * @param index  the index, starting from 0
529      * @param endMarkerAllowed  whether or not the end marker can be returned if
530      * startIndex is set to the list's size
531      * @return the node at the given index
532      * @throws IndexOutOfBoundsException if the index is less than 0; equal to
533      * the size of the list and endMakerAllowed is false; or greater than the
534      * size of the list
535      */
536     protected Node<E> getNode(final int index, final boolean endMarkerAllowed) throws IndexOutOfBoundsException {
537         // Check the index is within the bounds
538         if (index < 0) {
539             throw new IndexOutOfBoundsException("Couldn't get the node: " +
540                     "index (" + index + ") less than zero.");
541         }
542         if (!endMarkerAllowed && index == size) {
543             throw new IndexOutOfBoundsException("Couldn't get the node: " +
544                     "index (" + index + ") is the size of the list.");
545         }
546         if (index > size) {
547             throw new IndexOutOfBoundsException("Couldn't get the node: " +
548                     "index (" + index + ") greater than the size of the " +
549                     "list (" + size + ").");
550         }
551         // Search the list and get the node
552         Node<E> node;
553         if (index < size / 2) {
554             // Search forwards
555             node = header.next;
556             for (int currentIndex = 0; currentIndex < index; currentIndex++) {
557                 node = node.next;
558             }
559         } else {
560             // Search backwards
561             node = header;
562             for (int currentIndex = size; currentIndex > index; currentIndex--) {
563                 node = node.previous;
564             }
565         }
566         return node;
567     }
568 
569     //-----------------------------------------------------------------------
570     /**
571      * Creates an iterator for the sublist.
572      *
573      * @param subList  the sublist to get an iterator for
574      * @return a new iterator on the given sublist
575      */
576     protected Iterator<E> createSubListIterator(final LinkedSubList<E> subList) {
577         return createSubListListIterator(subList, 0);
578     }
579 
580     /**
581      * Creates a list iterator for the sublist.
582      *
583      * @param subList  the sublist to get an iterator for
584      * @param fromIndex  the index to start from, relative to the sublist
585      * @return a new list iterator on the given sublist
586      */
587     protected ListIterator<E> createSubListListIterator(final LinkedSubList<E> subList, final int fromIndex) {
588         return new LinkedSubListIterator<E>(subList, fromIndex);
589     }
590 
591     //-----------------------------------------------------------------------
592     /**
593      * Serializes the data held in this object to the stream specified.
594      * <p>
595      * The first serializable subclass must call this method from
596      * <code>writeObject</code>.
597      * 
598      * @param outputStream  the stream to write the object to
599      * @throws IOException  if anything goes wrong
600      */
601     protected void doWriteObject(final ObjectOutputStream outputStream) throws IOException {
602         // Write the size so we know how many nodes to read back
603         outputStream.writeInt(size());
604         for (final E e : this) {
605             outputStream.writeObject(e);
606         }
607     }
608 
609     /**
610      * Deserializes the data held in this object to the stream specified.
611      * <p>
612      * The first serializable subclass must call this method from
613      * <code>readObject</code>.
614      * 
615      * @param inputStream  the stream to read the object from
616      * @throws IOException  if any error occurs while reading from the stream
617      * @throws ClassNotFoundException  if a class read from the stream can not be loaded
618      */
619     @SuppressWarnings("unchecked")
620     protected void doReadObject(final ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
621         init();
622         final int size = inputStream.readInt();
623         for (int i = 0; i < size; i++) {
624             add((E) inputStream.readObject());
625         }
626     }
627 
628     //-----------------------------------------------------------------------
629     /**
630      * A node within the linked list.
631      * <p>
632      * From Commons Collections 3.1, all access to the <code>value</code> property
633      * is via the methods on this class.
634      */
635     protected static class Node<E> {
636 
637         /** A pointer to the node before this node */
638         protected Node<E> previous;
639         /** A pointer to the node after this node */
640         protected Node<E> next;
641         /** The object contained within this node */
642         protected E value;
643 
644         /**
645          * Constructs a new header node.
646          */
647         protected Node() {
648             super();
649             previous = this;
650             next = this;
651         }
652 
653         /**
654          * Constructs a new node.
655          *
656          * @param value  the value to store
657          */
658         protected Node(final E value) {
659             super();
660             this.value = value;
661         }
662 
663         /**
664          * Constructs a new node.
665          *
666          * @param previous  the previous node in the list
667          * @param next  the next node in the list
668          * @param value  the value to store
669          */
670         protected Node(final Node<E> previous, final Node<E> next, final E value) {
671             super();
672             this.previous = previous;
673             this.next = next;
674             this.value = value;
675         }
676 
677         /**
678          * Gets the value of the node.
679          *
680          * @return the value
681          * @since 3.1
682          */
683         protected E getValue() {
684             return value;
685         }
686 
687         /**
688          * Sets the value of the node.
689          *
690          * @param value  the value
691          * @since 3.1
692          */
693         protected void setValue(final E value) {
694             this.value = value;
695         }
696 
697         /**
698          * Gets the previous node.
699          *
700          * @return the previous node
701          * @since 3.1
702          */
703         protected Node<E> getPreviousNode() {
704             return previous;
705         }
706 
707         /**
708          * Sets the previous node.
709          *
710          * @param previous  the previous node
711          * @since 3.1
712          */
713         protected void setPreviousNode(final Node<E> previous) {
714             this.previous = previous;
715         }
716 
717         /**
718          * Gets the next node.
719          *
720          * @return the next node
721          * @since 3.1
722          */
723         protected Node<E> getNextNode() {
724             return next;
725         }
726 
727         /**
728          * Sets the next node.
729          *
730          * @param next  the next node
731          * @since 3.1
732          */
733         protected void setNextNode(final Node<E> next) {
734             this.next = next;
735         }
736     }
737 
738     //-----------------------------------------------------------------------
739     /**
740      * A list iterator over the linked list.
741      */
742     protected static class LinkedListIterator<E> implements ListIterator<E>, OrderedIterator<E> {
743 
744         /** The parent list */
745         protected final AbstractLinkedList<E> parent;
746 
747         /**
748          * The node that will be returned by {@link #next()}. If this is equal
749          * to {@link AbstractLinkedList#header} then there are no more values to return.
750          */
751         protected Node<E> next;
752 
753         /**
754          * The index of {@link #next}.
755          */
756         protected int nextIndex;
757 
758         /**
759          * The last node that was returned by {@link #next()} or {@link
760          * #previous()}. Set to <code>null</code> if {@link #next()} or {@link
761          * #previous()} haven't been called, or if the node has been removed
762          * with {@link #remove()} or a new node added with {@link #add(Object)}.
763          * Should be accessed through {@link #getLastNodeReturned()} to enforce
764          * this behaviour.
765          */
766         protected Node<E> current;
767 
768         /**
769          * The modification count that the list is expected to have. If the list
770          * doesn't have this count, then a
771          * {@link java.util.ConcurrentModificationException} may be thrown by
772          * the operations.
773          */
774         protected int expectedModCount;
775 
776         /**
777          * Create a ListIterator for a list.
778          *
779          * @param parent  the parent list
780          * @param fromIndex  the index to start at
781          * @throws IndexOutOfBoundsException if fromIndex is less than 0 or greater than the size of the list
782          */
783         protected LinkedListIterator(final AbstractLinkedList<E> parent, final int fromIndex)
784                 throws IndexOutOfBoundsException {
785             super();
786             this.parent = parent;
787             this.expectedModCount = parent.modCount;
788             this.next = parent.getNode(fromIndex, true);
789             this.nextIndex = fromIndex;
790         }
791 
792         /**
793          * Checks the modification count of the list is the value that this
794          * object expects.
795          *
796          * @throws ConcurrentModificationException If the list's modification
797          * count isn't the value that was expected.
798          */
799         protected void checkModCount() {
800             if (parent.modCount != expectedModCount) {
801                 throw new ConcurrentModificationException();
802             }
803         }
804 
805         /**
806          * Gets the last node returned.
807          *
808          * @return the last node returned
809          * @throws IllegalStateException If {@link #next()} or {@link #previous()} haven't been called,
810          * or if the node has been removed with {@link #remove()} or a new node added with {@link #add(Object)}.
811          */
812         protected Node<E> getLastNodeReturned() throws IllegalStateException {
813             if (current == null) {
814                 throw new IllegalStateException();
815             }
816             return current;
817         }
818 
819         public boolean hasNext() {
820             return next != parent.header;
821         }
822 
823         public E next() {
824             checkModCount();
825             if (!hasNext()) {
826                 throw new NoSuchElementException("No element at index " + nextIndex + ".");
827             }
828             final E value = next.getValue();
829             current = next;
830             next = next.next;
831             nextIndex++;
832             return value;
833         }
834 
835         public boolean hasPrevious() {
836             return next.previous != parent.header;
837         }
838 
839         public E previous() {
840             checkModCount();
841             if (!hasPrevious()) {
842                 throw new NoSuchElementException("Already at start of list.");
843             }
844             next = next.previous;
845             final E value = next.getValue();
846             current = next;
847             nextIndex--;
848             return value;
849         }
850 
851         public int nextIndex() {
852             return nextIndex;
853         }
854 
855         public int previousIndex() {
856             // not normally overridden, as relative to nextIndex()
857             return nextIndex() - 1;
858         }
859 
860         public void remove() {
861             checkModCount();
862             if (current == next) {
863                 // remove() following previous()
864                 next = next.next;
865                 parent.removeNode(getLastNodeReturned());
866             } else {
867                 // remove() following next()
868                 parent.removeNode(getLastNodeReturned());
869                 nextIndex--;
870             }
871             current = null;
872             expectedModCount++;
873         }
874 
875         public void set(final E obj) {
876             checkModCount();
877             getLastNodeReturned().setValue(obj);
878         }
879 
880         public void add(final E obj) {
881             checkModCount();
882             parent.addNodeBefore(next, obj);
883             current = null;
884             nextIndex++;
885             expectedModCount++;
886         }
887 
888     }
889 
890     //-----------------------------------------------------------------------
891     /**
892      * A list iterator over the linked sub list.
893      */
894     protected static class LinkedSubListIterator<E> extends LinkedListIterator<E> {
895 
896         /** The parent list */
897         protected final LinkedSubList<E> sub;
898 
899         protected LinkedSubListIterator(final LinkedSubList<E> sub, final int startIndex) {
900             super(sub.parent, startIndex + sub.offset);
901             this.sub = sub;
902         }
903 
904         @Override
905         public boolean hasNext() {
906             return nextIndex() < sub.size;
907         }
908 
909         @Override
910         public boolean hasPrevious() {
911             return previousIndex() >= 0;
912         }
913 
914         @Override
915         public int nextIndex() {
916             return super.nextIndex() - sub.offset;
917         }
918 
919         @Override
920         public void add(final E obj) {
921             super.add(obj);
922             sub.expectedModCount = parent.modCount;
923             sub.size++;
924         }
925 
926         @Override
927         public void remove() {
928             super.remove();
929             sub.expectedModCount = parent.modCount;
930             sub.size--;
931         }
932     }
933 
934     //-----------------------------------------------------------------------
935     /**
936      * The sublist implementation for AbstractLinkedList.
937      */
938     protected static class LinkedSubList<E> extends AbstractList<E> {
939         /** The main list */
940         AbstractLinkedList<E> parent;
941         /** Offset from the main list */
942         int offset;
943         /** Sublist size */
944         int size;
945         /** Sublist modCount */
946         int expectedModCount;
947 
948         protected LinkedSubList(final AbstractLinkedList<E> parent, final int fromIndex, final int toIndex) {
949             if (fromIndex < 0) {
950                 throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
951             }
952             if (toIndex > parent.size()) {
953                 throw new IndexOutOfBoundsException("toIndex = " + toIndex);
954             }
955             if (fromIndex > toIndex) {
956                 throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
957             }
958             this.parent = parent;
959             this.offset = fromIndex;
960             this.size = toIndex - fromIndex;
961             this.expectedModCount = parent.modCount;
962         }
963 
964         @Override
965         public int size() {
966             checkModCount();
967             return size;
968         }
969 
970         @Override
971         public E get(final int index) {
972             rangeCheck(index, size);
973             checkModCount();
974             return parent.get(index + offset);
975         }
976 
977         @Override
978         public void add(final int index, final E obj) {
979             rangeCheck(index, size + 1);
980             checkModCount();
981             parent.add(index + offset, obj);
982             expectedModCount = parent.modCount;
983             size++;
984             LinkedSubList.this.modCount++;
985         }
986 
987         @Override
988         public E remove(final int index) {
989             rangeCheck(index, size);
990             checkModCount();
991             final E result = parent.remove(index + offset);
992             expectedModCount = parent.modCount;
993             size--;
994             LinkedSubList.this.modCount++;
995             return result;
996         }
997 
998         @Override
999         public boolean addAll(final Collection<? extends E> coll) {
1000             return addAll(size, coll);
1001         }
1002 
1003         @Override
1004         public boolean addAll(final int index, final Collection<? extends E> coll) {
1005             rangeCheck(index, size + 1);
1006             final int cSize = coll.size();
1007             if (cSize == 0) {
1008                 return false;
1009             }
1010 
1011             checkModCount();
1012             parent.addAll(offset + index, coll);
1013             expectedModCount = parent.modCount;
1014             size += cSize;
1015             LinkedSubList.this.modCount++;
1016             return true;
1017         }
1018 
1019         @Override
1020         public E set(final int index, final E obj) {
1021             rangeCheck(index, size);
1022             checkModCount();
1023             return parent.set(index + offset, obj);
1024         }
1025 
1026         @Override
1027         public void clear() {
1028             checkModCount();
1029             final Iterator<E> it = iterator();
1030             while (it.hasNext()) {
1031                 it.next();
1032                 it.remove();
1033             }
1034         }
1035 
1036         @Override
1037         public Iterator<E> iterator() {
1038             checkModCount();
1039             return parent.createSubListIterator(this);
1040         }
1041 
1042         @Override
1043         public ListIterator<E> listIterator(final int index) {
1044             rangeCheck(index, size + 1);
1045             checkModCount();
1046             return parent.createSubListListIterator(this, index);
1047         }
1048 
1049         @Override
1050         public List<E> subList(final int fromIndexInclusive, final int toIndexExclusive) {
1051             return new LinkedSubList<E>(parent, fromIndexInclusive + offset, toIndexExclusive + offset);
1052         }
1053 
1054         protected void rangeCheck(final int index, final int beyond) {
1055             if (index < 0 || index >= beyond) {
1056                 throw new IndexOutOfBoundsException("Index '" + index + "' out of bounds for size '" + size + "'");
1057             }
1058         }
1059 
1060         protected void checkModCount() {
1061             if (parent.modCount != expectedModCount) {
1062                 throw new ConcurrentModificationException();
1063             }
1064         }
1065     }
1066 
1067 }