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