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