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 *      https://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.util.AbstractList;
020import java.util.ArrayDeque;
021import java.util.Collection;
022import java.util.ConcurrentModificationException;
023import java.util.Deque;
024import java.util.Iterator;
025import java.util.List;
026import java.util.ListIterator;
027import java.util.NoSuchElementException;
028import java.util.Objects;
029
030import org.apache.commons.collections4.CollectionUtils;
031import org.apache.commons.collections4.OrderedIterator;
032
033/**
034 * A {@code List} implementation that is optimized for fast insertions and
035 * removals at any index in the list.
036 * <p>
037 * This list implementation utilizes a tree structure internally to ensure that
038 * all insertions and removals are O(log n). This provides much faster performance
039 * than both an {@code ArrayList} and a {@code LinkedList} where elements
040 * are inserted and removed repeatedly from anywhere in the list.
041 * </p>
042 * <p>
043 * The following relative performance statistics are indicative of this class:
044 * </p>
045 * <pre>
046 *              get  add  insert  iterate  remove
047 * TreeList       3    5       1       2       1
048 * ArrayList      1    1      40       1      40
049 * LinkedList  5800    1     350       2     325
050 * </pre>
051 * <p>
052 * {@code ArrayList} is a good general purpose list implementation.
053 * It is faster than {@code TreeList} for most operations except inserting
054 * and removing in the middle of the list. {@code ArrayList} also uses less
055 * memory as {@code TreeList} uses one object per entry.
056 * </p>
057 * <p>
058 * {@code LinkedList} is rarely a good choice of implementation.
059 * {@code TreeList} is almost always a good replacement for it, although it
060 * does use slightly more memory.
061 * </p>
062 *
063 * @param <E> The type of the elements in the list.
064 * @since 3.1
065 */
066public class TreeList<E> extends AbstractList<E> {
067//    add; toArray; iterator; insert; get; indexOf; remove
068//    TreeList = 1260;7360;3080;  160;   170;3400;  170;
069//   ArrayList =  220;1480;1760; 6870;    50;1540; 7200;
070//  LinkedList =  270;7360;3350;55860;290720;2910;55200;
071
072    /**
073     * Implements an AVLNode which keeps the offset updated.
074     * <p>
075     * This node contains the real work.
076     * TreeList is just there to implement {@link List}.
077     * The nodes don't know the index of the object they are holding.  They
078     * do know however their position relative to their parent node.
079     * This allows to calculate the index of a node while traversing the tree.
080     * </p>
081     * <p>
082     * The Faedelung calculation stores a flag for both the left and right child
083     * to indicate if they are a child (false) or a link as in linked list (true).
084     * </p>
085     */
086    static class AVLNode<E> {
087
088        /** The left child node or the predecessor if {@link #leftIsPrevious}.*/
089        private AVLNode<E> left;
090
091        /** Flag indicating that left reference is not a subtree but the predecessor. */
092        private boolean leftIsPrevious;
093
094        /** The right child node or the successor if {@link #rightIsNext}. */
095        private AVLNode<E> right;
096
097        /** Flag indicating that right reference is not a subtree but the successor. */
098        private boolean rightIsNext;
099
100        /** How many levels of left/right are below this one. */
101        private int height;
102
103        /** The relative position, root holds absolute position. */
104        private int relativePosition;
105
106        /** The stored element. */
107        private E value;
108
109        /**
110         * Constructs a new AVL tree from a collection.
111         * <p>
112         * The collection must be nonempty.
113         *
114         * @param coll  A nonempty collection
115         */
116        private AVLNode(final Collection<? extends E> coll) {
117            this(coll.iterator(), 0, coll.size() - 1, 0, null, null);
118        }
119
120        /**
121         * Constructs a new node with a relative position.
122         *
123         * @param relativePosition  The relative position of the node
124         * @param obj  The value for the node
125         * @param rightFollower The node with the value following this one
126         * @param leftFollower The node with the value leading this one
127         */
128        private AVLNode(final int relativePosition, final E obj,
129                        final AVLNode<E> rightFollower, final AVLNode<E> leftFollower) {
130            this.relativePosition = relativePosition;
131            value = obj;
132            rightIsNext = true;
133            leftIsPrevious = true;
134            right = rightFollower;
135            left = leftFollower;
136        }
137
138        /**
139         * Constructs a new AVL tree from a collection.
140         * <p>
141         * This is a recursive helper for {@link #AVLNode(Collection)}. A call
142         * to this method will construct the subtree for elements {@code start}
143         * through {@code end} of the collection, assuming the iterator
144         * {@code e} already points at element {@code start}.
145         * </p>
146         *
147         * @param iterator  An iterator over the collection, which should already point
148         *          to the element at index {@code start} within the collection
149         * @param start  The index of the first element in the collection that
150         *          should be in this subtree
151         * @param end  The index of the last element in the collection that
152         *          should be in this subtree
153         * @param absolutePositionOfParent  absolute position of this node's
154         *          parent, or 0 if this node is the root
155         * @param prev  The {@code AVLNode} corresponding to element (start - 1)
156         *          of the collection, or null if start is 0
157         * @param next  The {@code AVLNode} corresponding to element (end + 1)
158         *          of the collection, or null if end is the last element of the collection
159         */
160        private AVLNode(final Iterator<? extends E> iterator, final int start, final int end,
161                        final int absolutePositionOfParent, final AVLNode<E> prev, final AVLNode<E> next) {
162            final int mid = start + (end - start) / 2;
163            if (start < mid) {
164                left = new AVLNode<>(iterator, start, mid - 1, mid, prev, this);
165            } else {
166                leftIsPrevious = true;
167                left = prev;
168            }
169            value = iterator.next();
170            relativePosition = mid - absolutePositionOfParent;
171            if (mid < end) {
172                right = new AVLNode<>(iterator, mid + 1, end, mid, this, next);
173            } else {
174                rightIsNext = true;
175                right = next;
176            }
177            recalcHeight();
178        }
179
180        /**
181         * Appends the elements of another tree list to this tree list by efficiently
182         * merging the two AVL trees. This operation is destructive to both trees and
183         * runs in O(log(m + n)) time.
184         *
185         * @param otherTree
186         *            the root of the AVL tree to merge with this one
187         * @param currentSize
188         *            the number of elements in this AVL tree
189         * @return The root of the new, merged AVL tree
190         */
191        private AVLNode<E> addAll(AVLNode<E> otherTree, final int currentSize) {
192            final AVLNode<E> maxNode = max();
193            final AVLNode<E> otherTreeMin = otherTree.min();
194
195            // We need to efficiently merge the two AVL trees while keeping them
196            // balanced (or nearly balanced). To do this, we take the shorter
197            // tree and combine it with a similar-height subtree of the taller
198            // tree. There are two symmetric cases:
199            //   * this tree is taller, or
200            //   * otherTree is taller.
201            if (otherTree.height > height) {
202                // CASE 1: The other tree is taller than this one. We will thus
203                // merge this tree into otherTree.
204
205                // STEP 1: Remove the maximum element from this tree.
206                final AVLNode<E> leftSubTree = removeMax();
207
208                // STEP 2: Navigate left from the root of otherTree until we
209                // find a subtree, s, that is no taller than me. (While we are
210                // navigating left, we store the nodes we encounter in a stack
211                // so that we can re-balance them in step 4.)
212                final Deque<AVLNode<E>> sAncestors = new ArrayDeque<>();
213                AVLNode<E> s = otherTree;
214                int sAbsolutePosition = s.relativePosition + currentSize;
215                int sParentAbsolutePosition = 0;
216                while (s != null && s.height > getHeight(leftSubTree)) {
217                    sParentAbsolutePosition = sAbsolutePosition;
218                    sAncestors.push(s);
219                    s = s.left;
220                    if (s != null) {
221                        sAbsolutePosition += s.relativePosition;
222                    }
223                }
224
225                // STEP 3: Replace s with a newly constructed subtree whose root
226                // is maxNode, whose left subtree is leftSubTree, and whose right
227                // subtree is s.
228                maxNode.setLeft(leftSubTree, null);
229                maxNode.setRight(s, otherTreeMin);
230                if (leftSubTree != null) {
231                    leftSubTree.max().setRight(null, maxNode);
232                    leftSubTree.relativePosition -= currentSize - 1;
233                }
234                if (s != null) {
235                    s.min().setLeft(null, maxNode);
236                    s.relativePosition = sAbsolutePosition - currentSize + 1;
237                }
238                maxNode.relativePosition = currentSize - 1 - sParentAbsolutePosition;
239                otherTree.relativePosition += currentSize;
240
241                // STEP 4: Re-balance the tree and recalculate the heights of s's ancestors.
242                s = maxNode;
243                while (!sAncestors.isEmpty()) {
244                    final AVLNode<E> sAncestor = sAncestors.pop();
245                    sAncestor.setLeft(s, null);
246                    s = sAncestor.balance();
247                }
248                return s;
249            }
250            otherTree = otherTree.removeMin();
251
252            final Deque<AVLNode<E>> sAncestors = new ArrayDeque<>();
253            AVLNode<E> s = this;
254            int sAbsolutePosition = s.relativePosition;
255            int sParentAbsolutePosition = 0;
256            while (s != null && s.height > getHeight(otherTree)) {
257                sParentAbsolutePosition = sAbsolutePosition;
258                sAncestors.push(s);
259                s = s.right;
260                if (s != null) {
261                    sAbsolutePosition += s.relativePosition;
262                }
263            }
264
265            otherTreeMin.setRight(otherTree, null);
266            otherTreeMin.setLeft(s, maxNode);
267            if (otherTree != null) {
268                otherTree.min().setLeft(null, otherTreeMin);
269                otherTree.relativePosition++;
270            }
271            if (s != null) {
272                s.max().setRight(null, otherTreeMin);
273                s.relativePosition = sAbsolutePosition - currentSize;
274            }
275            otherTreeMin.relativePosition = currentSize - sParentAbsolutePosition;
276
277            s = otherTreeMin;
278            while (!sAncestors.isEmpty()) {
279                final AVLNode<E> sAncestor = sAncestors.pop();
280                sAncestor.setRight(s, null);
281                s = sAncestor.balance();
282            }
283            return s;
284        }
285
286        /**
287         * Balances according to the AVL algorithm.
288         */
289        private AVLNode<E> balance() {
290            switch (heightRightMinusLeft()) {
291            case 1:
292            case 0:
293            case -1:
294                return this;
295            case -2:
296                if (left.heightRightMinusLeft() > 0) {
297                    setLeft(left.rotateLeft(), null);
298                }
299                return rotateRight();
300            case 2:
301                if (right.heightRightMinusLeft() < 0) {
302                    setRight(right.rotateRight(), null);
303                }
304                return rotateLeft();
305            default:
306                throw new IllegalStateException("tree inconsistent.");
307            }
308        }
309
310        /**
311         * Gets the element with the given index relative to the
312         * offset of the parent of this node.
313         */
314        AVLNode<E> get(final int index) {
315            final int indexRelativeToMe = index - relativePosition;
316
317            if (indexRelativeToMe == 0) {
318                return this;
319            }
320
321            final AVLNode<E> nextNode = indexRelativeToMe < 0 ? getLeftSubTree() : getRightSubTree();
322            if (nextNode == null) {
323                return null;
324            }
325            return nextNode.get(indexRelativeToMe);
326        }
327
328        /**
329         * Gets the height of the node or -1 if the node is null.
330         */
331        private int getHeight(final AVLNode<E> node) {
332            return node == null ? -1 : node.height;
333        }
334
335        /**
336         * Gets the left node, returning null if it's a faedelung.
337         */
338        private AVLNode<E> getLeftSubTree() {
339            return leftIsPrevious ? null : left;
340        }
341
342        /**
343         * Gets the relative position.
344         */
345        private int getOffset(final AVLNode<E> node) {
346            if (node == null) {
347                return 0;
348            }
349            return node.relativePosition;
350        }
351
352        /**
353         * Gets the right node, returning null if it's a faedelung.
354         */
355        private AVLNode<E> getRightSubTree() {
356            return rightIsNext ? null : right;
357        }
358
359        /**
360         * Gets the value.
361         *
362         * @return The value of this node
363         */
364        E getValue() {
365            return value;
366        }
367
368        /**
369         * Returns the height difference right - left
370         */
371        private int heightRightMinusLeft() {
372            return getHeight(getRightSubTree()) - getHeight(getLeftSubTree());
373        }
374
375        /**
376         * Finds the index that contains the specified object.
377         */
378        int indexOf(final Object object, final int index) {
379            if (getLeftSubTree() != null) {
380                final int result = left.indexOf(object, index + left.relativePosition);
381                if (result != -1) {
382                    return result;
383                }
384            }
385            if (Objects.equals(value, object)) {
386                return index;
387            }
388            if (getRightSubTree() != null) {
389                return right.indexOf(object, index + right.relativePosition);
390            }
391            return -1;
392        }
393
394        /**
395         * Inserts a node at the position index.
396         *
397         * @param index is the index of the position relative to the position of
398         * the parent node.
399         * @param obj is the object to be stored in the position.
400         */
401        AVLNode<E> insert(final int index, final E obj) {
402            final int indexRelativeToMe = index - relativePosition;
403
404            if (indexRelativeToMe <= 0) {
405                return insertOnLeft(indexRelativeToMe, obj);
406            }
407            return insertOnRight(indexRelativeToMe, obj);
408        }
409
410        private AVLNode<E> insertOnLeft(final int indexRelativeToMe, final E obj) {
411            if (getLeftSubTree() == null) {
412                setLeft(new AVLNode<>(-1, obj, this, left), null);
413            } else {
414                setLeft(left.insert(indexRelativeToMe, obj), null);
415            }
416
417            if (relativePosition >= 0) {
418                relativePosition++;
419            }
420            final AVLNode<E> ret = balance();
421            recalcHeight();
422            return ret;
423        }
424
425        private AVLNode<E> insertOnRight(final int indexRelativeToMe, final E obj) {
426            if (getRightSubTree() == null) {
427                setRight(new AVLNode<>(+1, obj, right, this), null);
428            } else {
429                setRight(right.insert(indexRelativeToMe, obj), null);
430            }
431            if (relativePosition < 0) {
432                relativePosition--;
433            }
434            final AVLNode<E> ret = balance();
435            recalcHeight();
436            return ret;
437        }
438
439        /**
440         * Gets the rightmost child of this node.
441         *
442         * @return The rightmost child (greatest index)
443         */
444        private AVLNode<E> max() {
445            return getRightSubTree() == null ? this : right.max();
446        }
447
448        /**
449         * Gets the leftmost child of this node.
450         *
451         * @return The leftmost child (smallest index)
452         */
453        private AVLNode<E> min() {
454            return getLeftSubTree() == null ? this : left.min();
455        }
456
457        /**
458         * Gets the next node in the list after this one.
459         *
460         * @return The next node
461         */
462        AVLNode<E> next() {
463            if (rightIsNext || right == null) {
464                return right;
465            }
466            return right.min();
467        }
468
469        /**
470         * Gets the node in the list before this one.
471         *
472         * @return The previous node
473         */
474        AVLNode<E> previous() {
475            if (leftIsPrevious || left == null) {
476                return left;
477            }
478            return left.max();
479        }
480
481        /**
482         * Sets the height by calculation.
483         */
484        private void recalcHeight() {
485            height = Math.max(
486                getLeftSubTree() == null ? -1 : getLeftSubTree().height,
487                getRightSubTree() == null ? -1 : getRightSubTree().height) + 1;
488        }
489
490        /**
491         * Removes the node at a given position.
492         *
493         * @param index is the index of the element to be removed relative to the position of
494         * the parent node of the current node.
495         */
496        AVLNode<E> remove(final int index) {
497            final int indexRelativeToMe = index - relativePosition;
498
499            if (indexRelativeToMe == 0) {
500                return removeSelf();
501            }
502            if (indexRelativeToMe > 0) {
503                setRight(right.remove(indexRelativeToMe), right.right);
504                if (relativePosition < 0) {
505                    relativePosition++;
506                }
507            } else {
508                setLeft(left.remove(indexRelativeToMe), left.left);
509                if (relativePosition > 0) {
510                    relativePosition--;
511                }
512            }
513            recalcHeight();
514            return balance();
515        }
516
517        private AVLNode<E> removeMax() {
518            if (getRightSubTree() == null) {
519                return removeSelf();
520            }
521            setRight(right.removeMax(), right.right);
522            if (relativePosition < 0) {
523                relativePosition++;
524            }
525            recalcHeight();
526            return balance();
527        }
528
529        private AVLNode<E> removeMin() {
530            if (getLeftSubTree() == null) {
531                return removeSelf();
532            }
533            setLeft(left.removeMin(), left.left);
534            if (relativePosition > 0) {
535                relativePosition--;
536            }
537            recalcHeight();
538            return balance();
539        }
540
541        /**
542         * Removes this node from the tree.
543         *
544         * @return The node that replaces this one in the parent
545         */
546        private AVLNode<E> removeSelf() {
547            if (getRightSubTree() == null && getLeftSubTree() == null) {
548                return null;
549            }
550            if (getRightSubTree() == null) {
551                if (relativePosition > 0) {
552                    left.relativePosition += relativePosition;
553                }
554                left.max().setRight(null, right);
555                return left;
556            }
557            if (getLeftSubTree() == null) {
558                right.relativePosition += relativePosition - (relativePosition < 0 ? 0 : 1);
559                right.min().setLeft(null, left);
560                return right;
561            }
562
563            if (heightRightMinusLeft() > 0) {
564                // more on the right, so delete from the right
565                final AVLNode<E> rightMin = right.min();
566                value = rightMin.value;
567                if (leftIsPrevious) {
568                    left = rightMin.left;
569                }
570                right = right.removeMin();
571                if (relativePosition < 0) {
572                    relativePosition++;
573                }
574            } else {
575                // more on the left or equal, so delete from the left
576                final AVLNode<E> leftMax = left.max();
577                value = leftMax.value;
578                if (rightIsNext) {
579                    right = leftMax.right;
580                }
581                final AVLNode<E> leftPrevious = left.left;
582                left = left.removeMax();
583                if (left == null) {
584                    // special case where left that was deleted was a double link
585                    // only occurs when height difference is equal
586                    left = leftPrevious;
587                    leftIsPrevious = true;
588                }
589                if (relativePosition > 0) {
590                    relativePosition--;
591                }
592            }
593            recalcHeight();
594            return this;
595        }
596
597        private AVLNode<E> rotateLeft() {
598            final AVLNode<E> newTop = right; // can't be faedelung!
599            final AVLNode<E> movedNode = getRightSubTree().getLeftSubTree();
600
601            final int newTopPosition = relativePosition + getOffset(newTop);
602            final int myNewPosition = -newTop.relativePosition;
603            final int movedPosition = getOffset(newTop) + getOffset(movedNode);
604
605            setRight(movedNode, newTop);
606            newTop.setLeft(this, null);
607
608            setOffset(newTop, newTopPosition);
609            setOffset(this, myNewPosition);
610            setOffset(movedNode, movedPosition);
611            return newTop;
612        }
613
614        private AVLNode<E> rotateRight() {
615            final AVLNode<E> newTop = left; // can't be faedelung
616            final AVLNode<E> movedNode = getLeftSubTree().getRightSubTree();
617
618            final int newTopPosition = relativePosition + getOffset(newTop);
619            final int myNewPosition = -newTop.relativePosition;
620            final int movedPosition = getOffset(newTop) + getOffset(movedNode);
621
622            setLeft(movedNode, newTop);
623            newTop.setRight(this, null);
624
625            setOffset(newTop, newTopPosition);
626            setOffset(this, myNewPosition);
627            setOffset(movedNode, movedPosition);
628            return newTop;
629        }
630
631        /**
632         * Sets the left field to the node, or the previous node if that is null
633         *
634         * @param node  The new left subtree node
635         * @param previous  The previous node in the linked list
636         */
637        private void setLeft(final AVLNode<E> node, final AVLNode<E> previous) {
638            leftIsPrevious = node == null;
639            left = leftIsPrevious ? previous : node;
640            recalcHeight();
641        }
642
643        /**
644         * Sets the relative position.
645         */
646        private int setOffset(final AVLNode<E> node, final int newOffset) {
647            if (node == null) {
648                return 0;
649            }
650            final int oldOffset = getOffset(node);
651            node.relativePosition = newOffset;
652            return oldOffset;
653        }
654
655        /**
656         * Sets the right field to the node, or the next node if that is null
657         *
658         * @param node  The new left subtree node
659         * @param next  The next node in the linked list
660         */
661        private void setRight(final AVLNode<E> node, final AVLNode<E> next) {
662            rightIsNext = node == null;
663            right = rightIsNext ? next : node;
664            recalcHeight();
665        }
666
667        /**
668         * Sets the value.
669         *
670         * @param obj  The value to store
671         */
672        void setValue(final E obj) {
673            this.value = obj;
674        }
675
676        /**
677         * Stores the node and its children into the array specified.
678         *
679         * @param array The array to be filled
680         * @param index The index of this node
681         */
682        void toArray(final Object[] array, final int index) {
683            array[index] = value;
684            if (getLeftSubTree() != null) {
685                left.toArray(array, index + left.relativePosition);
686            }
687            if (getRightSubTree() != null) {
688                right.toArray(array, index + right.relativePosition);
689            }
690        }
691
692//      private void checkFaedelung() {
693//          AVLNode maxNode = left.max();
694//          if (!maxNode.rightIsFaedelung || maxNode.right != this) {
695//              throw new RuntimeException(maxNode + " should right-faedel to " + this);
696//          }
697//          AVLNode minNode = right.min();
698//          if (!minNode.leftIsFaedelung || minNode.left != this) {
699//              throw new RuntimeException(maxNode + " should left-faedel to " + this);
700//          }
701//      }
702//
703//        private int checkTreeDepth() {
704//            int hright = (getRightSubTree() == null ? -1 : getRightSubTree().checkTreeDepth());
705//            //          System.out.print("checkTreeDepth");
706//            //          System.out.print(this);
707//            //          System.out.print(" left: ");
708//            //          System.out.print(_left);
709//            //          System.out.print(" right: ");
710//            //          System.out.println(_right);
711//
712//            int hleft = (left == null ? -1 : left.checkTreeDepth());
713//            if (height != Math.max(hright, hleft) + 1) {
714//                throw new RuntimeException(
715//                    "height should be max" + hleft + "," + hright + " but is " + height);
716//            }
717//            return height;
718//        }
719//
720//        private int checkLeftSubNode() {
721//            if (getLeftSubTree() == null) {
722//                return 0;
723//            }
724//            int count = 1 + left.checkRightSubNode();
725//            if (left.relativePosition != -count) {
726//                throw new RuntimeException();
727//            }
728//            return count + left.checkLeftSubNode();
729//        }
730//
731//        private int checkRightSubNode() {
732//            AVLNode right = getRightSubTree();
733//            if (right == null) {
734//                return 0;
735//            }
736//            int count = 1;
737//            count += right.checkLeftSubNode();
738//            if (right.relativePosition != count) {
739//                throw new RuntimeException();
740//            }
741//            return count + right.checkRightSubNode();
742//        }
743
744        /**
745         * Used for debugging.
746         */
747        @Override
748        public String toString() {
749            return new StringBuilder()
750                .append("AVLNode(")
751                .append(relativePosition)
752                .append(CollectionUtils.COMMA)
753                .append(left != null)
754                .append(CollectionUtils.COMMA)
755                .append(value)
756                .append(CollectionUtils.COMMA)
757                .append(getRightSubTree() != null)
758                .append(rightIsNext)
759                .append(")")
760                .toString();
761        }
762    }
763
764    /**
765     * A list iterator over the linked list.
766     */
767    static class TreeListIterator<E> implements ListIterator<E>, OrderedIterator<E> {
768
769        /** The parent list */
770        private final TreeList<E> parent;
771
772        /**
773         * Cache of the next node that will be returned by {@link #next()}.
774         */
775        private AVLNode<E> next;
776
777        /**
778         * The index of the next node to be returned.
779         */
780        private int nextIndex;
781
782        /**
783         * Cache of the last node that was returned by {@link #next()}
784         * or {@link #previous()}.
785         */
786        private AVLNode<E> current;
787
788        /**
789         * The index of the last node that was returned.
790         */
791        private int currentIndex;
792
793        /**
794         * The modification count that the list is expected to have. If the list
795         * doesn't have this count, then a
796         * {@link ConcurrentModificationException} may be thrown by
797         * the operations.
798         */
799        private int expectedModCount;
800
801        /**
802         * Create a ListIterator for a list.
803         *
804         * @param parent  The parent list
805         * @param fromIndex  The index to start at
806         */
807        protected TreeListIterator(final TreeList<E> parent, final int fromIndex) {
808            checkInterval(fromIndex, 0, parent.size(), parent.size());
809            this.parent = parent;
810            this.expectedModCount = parent.modCount;
811            this.next = parent.root == null ? null : parent.root.get(fromIndex);
812            this.nextIndex = fromIndex;
813            this.currentIndex = -1;
814        }
815
816        @Override
817        public void add(final E obj) {
818            checkModCount();
819            parent.add(nextIndex, obj);
820            current = null;
821            currentIndex = -1;
822            nextIndex++;
823            expectedModCount++;
824        }
825
826        /**
827         * Checks the modification count of the list is the value that this
828         * object expects.
829         *
830         * @throws ConcurrentModificationException If the list's modification
831         * count isn't the value that was expected.
832         */
833        protected void checkModCount() {
834            if (parent.modCount != expectedModCount) {
835                throw new ConcurrentModificationException();
836            }
837        }
838
839        @Override
840        public boolean hasNext() {
841            return nextIndex < parent.size();
842        }
843
844        @Override
845        public boolean hasPrevious() {
846            return nextIndex > 0;
847        }
848
849        @Override
850        public E next() {
851            checkModCount();
852            if (!hasNext()) {
853                throw new NoSuchElementException("No element at index " + nextIndex + ".");
854            }
855            if (next == null) {
856                next = parent.root.get(nextIndex);
857            }
858            final E value = next.getValue();
859            current = next;
860            currentIndex = nextIndex++;
861            next = next.next();
862            return value;
863        }
864
865        @Override
866        public int nextIndex() {
867            return nextIndex;
868        }
869
870        @Override
871        public E previous() {
872            checkModCount();
873            if (!hasPrevious()) {
874                throw new NoSuchElementException("Already at start of list.");
875            }
876            if (next == null) {
877                next = parent.root.get(nextIndex - 1);
878            } else {
879                next = next.previous();
880            }
881            final E value = next.getValue();
882            current = next;
883            currentIndex = --nextIndex;
884            return value;
885        }
886
887        @Override
888        public int previousIndex() {
889            return nextIndex() - 1;
890        }
891
892        @Override
893        public void remove() {
894            checkModCount();
895            if (currentIndex == -1) {
896                throw new IllegalStateException();
897            }
898            parent.remove(currentIndex);
899            if (nextIndex != currentIndex) {
900                // remove() following next()
901                nextIndex--;
902            }
903            // the AVL node referenced by next may have become stale after a remove
904            // reset it now: will be retrieved by next call to next()/previous() via nextIndex
905            next = null;
906            current = null;
907            currentIndex = -1;
908            expectedModCount++;
909        }
910
911        @Override
912        public void set(final E obj) {
913            checkModCount();
914            if (current == null) {
915                throw new IllegalStateException();
916            }
917            current.setValue(obj);
918        }
919    }
920
921    /**
922     * Checks whether the index is valid.
923     *
924     * @param index  The index to check.
925     * @param startIndex  The first allowed index.
926     * @param endIndex  The last allowed index.
927     * @param endIndex  The size.
928     * @throws IndexOutOfBoundsException if the index is invalid
929     */
930    private static void checkInterval(final int index, final int startIndex, final int endIndex, final int size) {
931        if (index < startIndex || index > endIndex) {
932            throw new IndexOutOfBoundsException("Invalid index:" + index + ", size=" + size);
933        }
934    }
935
936    /** The root node in the AVL tree */
937    private AVLNode<E> root;
938
939    /** The current size of the list */
940    private int size;
941
942    /**
943     * Constructs a new empty list.
944     */
945    public TreeList() {
946    }
947
948    /**
949     * Constructs a new empty list that copies the specified collection.
950     *
951     * @param coll  The collection to copy
952     * @throws NullPointerException if the collection is null
953     */
954    public TreeList(final Collection<? extends E> coll) {
955        if (!coll.isEmpty()) {
956            root = new AVLNode<>(coll);
957            size = coll.size();
958        }
959    }
960
961    /**
962     * Adds a new element to the list.
963     *
964     * @param index  The index to add before
965     * @param obj  The element to add
966     */
967    @Override
968    public void add(final int index, final E obj) {
969        checkInterval(index, 0, size());
970        modCount++;
971        if (root == null) {
972            root = new AVLNode<>(index, obj, null, null);
973        } else {
974            root = root.insert(index, obj);
975        }
976        size++;
977    }
978
979    /**
980     * Appends all the elements in the specified collection to the end of this list,
981     * in the order that they are returned by the specified collection's Iterator.
982     * <p>
983     * This method runs in O(n + log m) time, where m is
984     * the size of this list and n is the size of {@code c}.
985     * </p>
986     *
987     * @param c  The collection to be added to this list
988     * @return {@code true} if this list changed as a result of the call
989     * @throws NullPointerException if the specified collection contains a
990     *         null element and this collection does not permit null elements,
991     *         or if the specified collection is null
992     */
993    @Override
994    public boolean addAll(final Collection<? extends E> c) {
995        if (c.isEmpty()) {
996            return false;
997        }
998        modCount += c.size();
999        final AVLNode<E> cTree = new AVLNode<>(c);
1000        root = root == null ? cTree : root.addAll(cTree, size);
1001        size += c.size();
1002        return true;
1003    }
1004
1005    /**
1006     * Checks whether the index is valid.
1007     *
1008     * @param index  The index to check
1009     * @param startIndex  The first allowed index
1010     * @param endIndex  The last allowed index
1011     * @throws IndexOutOfBoundsException if the index is invalid
1012     */
1013    private void checkInterval(final int index, final int startIndex, final int endIndex) {
1014        checkInterval(index, startIndex, endIndex, size());
1015    }
1016
1017    /**
1018     * Clears the list, removing all entries.
1019     */
1020    @Override
1021    public void clear() {
1022        modCount++;
1023        root = null;
1024        size = 0;
1025    }
1026
1027    /**
1028     * Searches for the presence of an object in the list.
1029     *
1030     * @param object  The object to check
1031     * @return true if the object is found
1032     */
1033    @Override
1034    public boolean contains(final Object object) {
1035        return indexOf(object) >= 0;
1036    }
1037
1038    /**
1039     * Gets the element at the specified index.
1040     *
1041     * @param index  The index to retrieve
1042     * @return The element at the specified index
1043     */
1044    @Override
1045    public E get(final int index) {
1046        checkInterval(index, 0, size() - 1);
1047        return root.get(index).getValue();
1048    }
1049
1050    /**
1051     * Searches for the index of an object in the list.
1052     *
1053     * @param object  The object to search
1054     * @return The index of the object, -1 if not found
1055     */
1056    @Override
1057    public int indexOf(final Object object) {
1058        // override to go 75% faster
1059        if (root == null) {
1060            return -1;
1061        }
1062        return root.indexOf(object, root.relativePosition);
1063    }
1064
1065    /**
1066     * Gets an iterator over the list.
1067     *
1068     * @return An iterator over the list
1069     */
1070    @Override
1071    public Iterator<E> iterator() {
1072        // override to go 75% faster
1073        return listIterator(0);
1074    }
1075
1076    /**
1077     * Gets a ListIterator over the list.
1078     *
1079     * @return The new iterator
1080     */
1081    @Override
1082    public ListIterator<E> listIterator() {
1083        // override to go 75% faster
1084        return listIterator(0);
1085    }
1086
1087    /**
1088     * Gets a ListIterator over the list.
1089     *
1090     * @param fromIndex  The index to start from.
1091     * @return The new iterator.
1092     */
1093    @Override
1094    public ListIterator<E> listIterator(final int fromIndex) {
1095        // override to go 75% faster
1096        // cannot use EmptyIterator as iterator.add() must work
1097        return new TreeListIterator<>(this, fromIndex);
1098    }
1099
1100    /**
1101     * Removes the element at the specified index.
1102     *
1103     * @param index  The index to remove
1104     * @return The previous object at that index
1105     */
1106    @Override
1107    public E remove(final int index) {
1108        checkInterval(index, 0, size() - 1);
1109        modCount++;
1110        final E result = get(index);
1111        root = root.remove(index);
1112        size--;
1113        return result;
1114    }
1115
1116    /**
1117     * Sets the element at the specified index.
1118     *
1119     * @param index  The index to set
1120     * @param obj  The object to store at the specified index
1121     * @return The previous object at that index
1122     * @throws IndexOutOfBoundsException if the index is invalid
1123     */
1124    @Override
1125    public E set(final int index, final E obj) {
1126        checkInterval(index, 0, size() - 1);
1127        final AVLNode<E> node = root.get(index);
1128        final E result = node.value;
1129        node.setValue(obj);
1130        return result;
1131    }
1132
1133    /**
1134     * Gets the current size of the list.
1135     *
1136     * @return The current size
1137     */
1138    @Override
1139    public int size() {
1140        return size;
1141    }
1142
1143    /**
1144     * Converts the list into an array.
1145     *
1146     * @return The list as an array
1147     */
1148    @Override
1149    public Object[] toArray() {
1150        // override to go 20% faster
1151        final Object[] array = new Object[size()];
1152        if (root != null) {
1153            root.toArray(array, root.relativePosition);
1154        }
1155        return array;
1156    }
1157
1158}