001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4.list;
018
019import java.io.IOException;
020import java.io.ObjectInputStream;
021import java.io.ObjectOutputStream;
022import java.lang.reflect.Array;
023import java.util.AbstractList;
024import java.util.Collection;
025import java.util.ConcurrentModificationException;
026import java.util.Iterator;
027import java.util.List;
028import java.util.ListIterator;
029import java.util.NoSuchElementException;
030
031import org.apache.commons.collections4.OrderedIterator;
032
033/**
034 * An abstract implementation of a linked list which provides numerous points for
035 * subclasses to override.
036 * <p>
037 * Overridable methods are provided to change the storage node and to change how
038 * nodes are added to and removed. Hopefully, all you need for unusual subclasses
039 * is here.
040 *
041 * @since 3.0
042 * @version $Id: AbstractLinkedList.html 972421 2015-11-14 20:00:04Z tn $
043 */
044public abstract class AbstractLinkedList<E> implements List<E> {
045
046    /*
047     * Implementation notes:
048     * - a standard circular doubly-linked list
049     * - a marker node is stored to mark the start and the end of the list
050     * - node creation and removal always occurs through createNode() and
051     *   removeNode().
052     * - a modification count is kept, with the same semantics as
053     * {@link java.util.LinkedList}.
054     * - respects {@link AbstractList#modCount}
055     */
056
057    /**
058     * A {@link Node} which indicates the start and end of the list and does not
059     * hold a value. The value of <code>next</code> is the first item in the
060     * list. The value of of <code>previous</code> is the last item in the list.
061     */
062    transient Node<E> header;
063
064    /** The size of the list */
065    transient int size;
066
067    /** Modification count for iterators */
068    transient int modCount;
069
070    /**
071     * Constructor that does nothing intended for deserialization.
072     * <p>
073     * If this constructor is used by a serializable subclass then the init()
074     * method must be called.
075     */
076    protected AbstractLinkedList() {
077        super();
078    }
079
080    /**
081     * Constructs a list copying data from the specified collection.
082     *
083     * @param coll  the collection to copy
084     */
085    protected AbstractLinkedList(final Collection<? extends E> coll) {
086        super();
087        init();
088        addAll(coll);
089    }
090
091    /**
092     * The equivalent of a default constructor, broken out so it can be called
093     * by any constructor and by <code>readObject</code>.
094     * Subclasses which override this method should make sure they call super,
095     * so the list is initialised properly.
096     */
097    protected void init() {
098        header = createHeaderNode();
099    }
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}