1. /*
  2. * Copyright 2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.collections.list;
  17. import java.util.AbstractList;
  18. import java.util.Collection;
  19. import java.util.ConcurrentModificationException;
  20. import java.util.Iterator;
  21. import java.util.ListIterator;
  22. import java.util.NoSuchElementException;
  23. import org.apache.commons.collections.OrderedIterator;
  24. /**
  25. * A <code>List</code> implementation that is optimised for fast insertions and
  26. * removals at any index in the list.
  27. * <p>
  28. * This list implementation utilises a tree structure internally to ensure that
  29. * all insertions and removals are O(log n). This provides much faster performance
  30. * than both an <code>ArrayList</code> and a <code>LinkedList</code> where elements
  31. * are inserted and removed repeatedly from anywhere in the list.
  32. * <p>
  33. * The following relative performance statistics are indicative of this class:
  34. * <pre>
  35. * get add insert iterate remove
  36. * TreeList 3 5 1 2 1
  37. * ArrayList 1 1 40 1 40
  38. * LinkedList 5800 1 350 2 325
  39. * </pre>
  40. * <code>ArrayList</code> is a good general purpose list implementation.
  41. * It is faster than <code>TreeList</code> for most operations except inserting
  42. * and removing in the middle of the list. <code>ArrayList</code> also uses less
  43. * memory as <code>TreeList</code> uses one object per entry.
  44. * <p>
  45. * <code>LinkedList</code> is rarely a good choice of implementation.
  46. * <code>TreeList</code> is almost always a good replacement for it, although it
  47. * does use sligtly more memory.
  48. *
  49. * @since Commons Collections 3.1
  50. * @version $Revision: 1.3 $ $Date: 2004/05/26 21:56:05 $
  51. *
  52. * @author Joerg Schmuecker
  53. * @author Stephen Colebourne
  54. */
  55. public class TreeList extends AbstractList {
  56. // add; toArray; iterator; insert; get; indexOf; remove
  57. // TreeList = 1260;7360;3080; 160; 170;3400; 170;
  58. // ArrayList = 220;1480;1760; 6870; 50;1540; 7200;
  59. // LinkedList = 270;7360;3350;55860;290720;2910;55200;
  60. /** The root node in the AVL tree */
  61. private AVLNode root;
  62. /** The current size of the list */
  63. private int size;
  64. //-----------------------------------------------------------------------
  65. /**
  66. * Constructs a new empty list.
  67. */
  68. public TreeList() {
  69. super();
  70. }
  71. /**
  72. * Constructs a new empty list that copies the specified list.
  73. *
  74. * @param coll the collection to copy
  75. * @throws NullPointerException if the collection is null
  76. */
  77. public TreeList(Collection coll) {
  78. super();
  79. addAll(coll);
  80. }
  81. //-----------------------------------------------------------------------
  82. /**
  83. * Gets the element at the specified index.
  84. *
  85. * @param index the index to retrieve
  86. * @return the element at the specified index
  87. */
  88. public Object get(int index) {
  89. checkInterval(index, 0, size() - 1);
  90. return root.get(index).getValue();
  91. }
  92. /**
  93. * Gets the current size of the list.
  94. *
  95. * @return the current size
  96. */
  97. public int size() {
  98. return size;
  99. }
  100. /**
  101. * Gets an iterator over the list.
  102. *
  103. * @return an iterator over the list
  104. */
  105. public Iterator iterator() {
  106. // override to go 75% faster
  107. return listIterator(0);
  108. }
  109. /**
  110. * Gets a ListIterator over the list.
  111. *
  112. * @return the new iterator
  113. */
  114. public ListIterator listIterator() {
  115. // override to go 75% faster
  116. return listIterator(0);
  117. }
  118. /**
  119. * Gets a ListIterator over the list.
  120. *
  121. * @param fromIndex the index to start from
  122. * @return the new iterator
  123. */
  124. public ListIterator listIterator(int fromIndex) {
  125. // override to go 75% faster
  126. // cannot use EmptyIterator as iterator.add() must work
  127. checkInterval(fromIndex, 0, size());
  128. return new TreeListIterator(this, fromIndex);
  129. }
  130. /**
  131. * Searches for the index of an object in the list.
  132. *
  133. * @return the index of the object, -1 if not found
  134. */
  135. public int indexOf(Object object) {
  136. // override to go 75% faster
  137. if (root == null) {
  138. return -1;
  139. }
  140. return root.indexOf(object, root.relativePosition);
  141. }
  142. /**
  143. * Searches for the presence of an object in the list.
  144. *
  145. * @return true if the object is found
  146. */
  147. public boolean contains(Object object) {
  148. return (indexOf(object) >= 0);
  149. }
  150. /**
  151. * Converts the list into an array.
  152. *
  153. * @return the list as an array
  154. */
  155. public Object[] toArray() {
  156. // override to go 20% faster
  157. Object[] array = new Object[size()];
  158. if (root != null) {
  159. root.toArray(array, root.relativePosition);
  160. }
  161. return array;
  162. }
  163. //-----------------------------------------------------------------------
  164. /**
  165. * Adds a new element to the list.
  166. *
  167. * @param index the index to add before
  168. * @param obj the element to add
  169. */
  170. public void add(int index, Object obj) {
  171. modCount++;
  172. checkInterval(index, 0, size());
  173. if (root == null) {
  174. root = new AVLNode(index, obj, null, null);
  175. } else {
  176. root = root.insert(index, obj);
  177. }
  178. size++;
  179. }
  180. /**
  181. * Sets the element at the specified index.
  182. *
  183. * @param index the index to set
  184. * @param obj the object to store at the specified index
  185. * @return the previous object at that index
  186. * @throws IndexOutOfBoundsException if the index is invalid
  187. */
  188. public Object set(int index, Object obj) {
  189. checkInterval(index, 0, size() - 1);
  190. AVLNode node = root.get(index);
  191. Object result = node.value;
  192. node.setValue(obj);
  193. return result;
  194. }
  195. /**
  196. * Removes the element at the specified index.
  197. *
  198. * @param index the index to remove
  199. * @return the previous object at that index
  200. */
  201. public Object remove(int index) {
  202. modCount++;
  203. checkInterval(index, 0, size() - 1);
  204. Object result = get(index);
  205. root = root.remove(index);
  206. size--;
  207. return result;
  208. }
  209. /**
  210. * Clears the list, removing all entries.
  211. */
  212. public void clear() {
  213. modCount++;
  214. root = null;
  215. size = 0;
  216. }
  217. //-----------------------------------------------------------------------
  218. /**
  219. * Checks whether the index is valid.
  220. *
  221. * @param index the index to check
  222. * @param startIndex the first allowed index
  223. * @param endIndex the last allowed index
  224. * @throws IndexOutOfBoundsException if the index is invalid
  225. */
  226. private void checkInterval(int index, int startIndex, int endIndex) {
  227. if (index < startIndex || index > endIndex) {
  228. throw new IndexOutOfBoundsException("Invalid index:" + index + ", size=" + size());
  229. }
  230. }
  231. //-----------------------------------------------------------------------
  232. /**
  233. * Implements an AVLNode which keeps the offset updated.
  234. * <p>
  235. * This node contains the real work.
  236. * TreeList is just there to implement {@link java.util.List}.
  237. * The nodes don't know the index of the object they are holding. They
  238. * do know however their position relative to their parent node.
  239. * This allows to calculate the index of a node while traversing the tree.
  240. * <p>
  241. * The Faedelung calculation stores a flag for both the left and right child
  242. * to indicate if they are a child (false) or a link as in linked list (true).
  243. */
  244. static class AVLNode {
  245. /** The left child node or the predecessor if {@link #leftIsPrevious}.*/
  246. private AVLNode left;
  247. /** Flag indicating that left reference is not a subtree but the predecessor. */
  248. private boolean leftIsPrevious;
  249. /** The right child node or the successor if {@link #rightIsNext}. */
  250. private AVLNode right;
  251. /** Flag indicating that right reference is not a subtree but the successor. */
  252. private boolean rightIsNext;
  253. /** How many levels of left/right are below this one. */
  254. private int height;
  255. /** The relative position, root holds absolute position. */
  256. private int relativePosition;
  257. /** The stored element. */
  258. private Object value;
  259. /**
  260. * Constructs a new node with a relative position.
  261. *
  262. * @param relativePosition the relative position of the node
  263. * @param obj the value for the ndoe
  264. * @param rightFollower the node with the value following this one
  265. * @param leftFollower the node with the value leading this one
  266. */
  267. private AVLNode(int relativePosition, Object obj, AVLNode rightFollower, AVLNode leftFollower) {
  268. this.relativePosition = relativePosition;
  269. value = obj;
  270. rightIsNext = true;
  271. leftIsPrevious = true;
  272. right = rightFollower;
  273. left = leftFollower;
  274. }
  275. /**
  276. * Gets the value.
  277. *
  278. * @return the value of this node
  279. */
  280. Object getValue() {
  281. return value;
  282. }
  283. /**
  284. * Sets the value.
  285. *
  286. * @param obj the value to store
  287. */
  288. void setValue(Object obj) {
  289. this.value = obj;
  290. }
  291. /**
  292. * Locate the element with the given index relative to the
  293. * offset of the parent of this node.
  294. */
  295. AVLNode get(int index) {
  296. int indexRelativeToMe = index - relativePosition;
  297. if (indexRelativeToMe == 0) {
  298. return this;
  299. }
  300. AVLNode nextNode = ((indexRelativeToMe < 0) ? getLeftSubTree() : getRightSubTree());
  301. if (nextNode == null) {
  302. return null;
  303. }
  304. return nextNode.get(indexRelativeToMe);
  305. }
  306. /**
  307. * Locate the index that contains the specified object.
  308. */
  309. int indexOf(Object object, int index) {
  310. if (getLeftSubTree() != null) {
  311. int result = left.indexOf(object, index + left.relativePosition);
  312. if (result != -1) {
  313. return result;
  314. }
  315. }
  316. if (value == null ? value == object : value.equals(object)) {
  317. return index;
  318. }
  319. if (getRightSubTree() != null) {
  320. return right.indexOf(object, index + right.relativePosition);
  321. }
  322. return -1;
  323. }
  324. /**
  325. * Stores the node and its children into the array specified.
  326. *
  327. * @param array the array to be filled
  328. * @param index the index of this node
  329. */
  330. void toArray(Object[] array, int index) {
  331. array[index] = value;
  332. if (getLeftSubTree() != null) {
  333. left.toArray(array, index + left.relativePosition);
  334. }
  335. if (getRightSubTree() != null) {
  336. right.toArray(array, index + right.relativePosition);
  337. }
  338. }
  339. /**
  340. * Gets the next node in the list after this one.
  341. *
  342. * @return the next node
  343. */
  344. AVLNode next() {
  345. if (rightIsNext || right == null) {
  346. return right;
  347. }
  348. return right.min();
  349. }
  350. /**
  351. * Gets the node in the list before this one.
  352. *
  353. * @return the previous node
  354. */
  355. AVLNode previous() {
  356. if (leftIsPrevious || left == null) {
  357. return left;
  358. }
  359. return left.max();
  360. }
  361. /**
  362. * Inserts a node at the position index.
  363. *
  364. * @param index is the index of the position relative to the position of
  365. * the parent node.
  366. * @param obj is the object to be stored in the position.
  367. */
  368. AVLNode insert(int index, Object obj) {
  369. int indexRelativeToMe = index - relativePosition;
  370. if (indexRelativeToMe <= 0) {
  371. return insertOnLeft(indexRelativeToMe, obj);
  372. } else {
  373. return insertOnRight(indexRelativeToMe, obj);
  374. }
  375. }
  376. private AVLNode insertOnLeft(int indexRelativeToMe, Object obj) {
  377. AVLNode ret = this;
  378. if (getLeftSubTree() == null) {
  379. setLeft(new AVLNode(-1, obj, this, left), null);
  380. } else {
  381. setLeft(left.insert(indexRelativeToMe, obj), null);
  382. }
  383. if (relativePosition >= 0) {
  384. relativePosition++;
  385. }
  386. ret = balance();
  387. recalcHeight();
  388. return ret;
  389. }
  390. private AVLNode insertOnRight(int indexRelativeToMe, Object obj) {
  391. AVLNode ret = this;
  392. if (getRightSubTree() == null) {
  393. setRight(new AVLNode(+1, obj, right, this), null);
  394. } else {
  395. setRight(right.insert(indexRelativeToMe, obj), null);
  396. }
  397. if (relativePosition < 0) {
  398. relativePosition--;
  399. }
  400. ret = balance();
  401. recalcHeight();
  402. return ret;
  403. }
  404. //-----------------------------------------------------------------------
  405. /**
  406. * Gets the left node, returning null if its a faedelung.
  407. */
  408. private AVLNode getLeftSubTree() {
  409. return (leftIsPrevious ? null : left);
  410. }
  411. /**
  412. * Gets the right node, returning null if its a faedelung.
  413. */
  414. private AVLNode getRightSubTree() {
  415. return (rightIsNext ? null : right);
  416. }
  417. /**
  418. * Gets the rightmost child of this node.
  419. *
  420. * @return the rightmost child (greatest index)
  421. */
  422. private AVLNode max() {
  423. return (getRightSubTree() == null) ? this : right.max();
  424. }
  425. /**
  426. * Gets the leftmost child of this node.
  427. *
  428. * @return the leftmost child (smallest index)
  429. */
  430. private AVLNode min() {
  431. return (getLeftSubTree() == null) ? this : left.min();
  432. }
  433. /**
  434. * Removes the node at a given position.
  435. *
  436. * @param index is the index of the element to be removed relative to the position of
  437. * the parent node of the current node.
  438. */
  439. AVLNode remove(int index) {
  440. int indexRelativeToMe = index - relativePosition;
  441. if (indexRelativeToMe == 0) {
  442. return removeSelf();
  443. }
  444. if (indexRelativeToMe > 0) {
  445. setRight(right.remove(indexRelativeToMe), right.right);
  446. if (relativePosition < 0) {
  447. relativePosition++;
  448. }
  449. } else {
  450. setLeft(left.remove(indexRelativeToMe), left.left);
  451. if (relativePosition > 0) {
  452. relativePosition--;
  453. }
  454. }
  455. recalcHeight();
  456. return balance();
  457. }
  458. private AVLNode removeMax() {
  459. if (getRightSubTree() == null) {
  460. return removeSelf();
  461. }
  462. setRight(right.removeMax(), right.right);
  463. if (relativePosition < 0) {
  464. relativePosition++;
  465. }
  466. recalcHeight();
  467. return balance();
  468. }
  469. private AVLNode removeMin() {
  470. if (getLeftSubTree() == null) {
  471. return removeSelf();
  472. }
  473. setLeft(left.removeMin(), left.left);
  474. if (relativePosition > 0) {
  475. relativePosition--;
  476. }
  477. recalcHeight();
  478. return balance();
  479. }
  480. private AVLNode removeSelf() {
  481. if (getRightSubTree() == null && getLeftSubTree() == null)
  482. return null;
  483. if (getRightSubTree() == null) {
  484. if (relativePosition > 0) {
  485. left.relativePosition += relativePosition + (relativePosition > 0 ? 0 : 1);
  486. }
  487. left.max().setRight(null, right);
  488. return left;
  489. }
  490. if (getLeftSubTree() == null) {
  491. right.relativePosition += relativePosition - (relativePosition < 0 ? 0 : 1);
  492. right.min().setLeft(null, left);
  493. return right;
  494. }
  495. if (heightRightMinusLeft() > 0) {
  496. AVLNode rightMin = right.min();
  497. value = rightMin.value;
  498. if (leftIsPrevious) {
  499. left = rightMin.left;
  500. }
  501. right = right.removeMin();
  502. if (relativePosition < 0) {
  503. relativePosition++;
  504. }
  505. } else {
  506. AVLNode leftMax = left.max();
  507. value = leftMax.value;
  508. if (rightIsNext) {
  509. right = leftMax.right;
  510. }
  511. left = left.removeMax();
  512. if (relativePosition > 0) {
  513. relativePosition--;
  514. }
  515. }
  516. recalcHeight();
  517. return this;
  518. }
  519. //-----------------------------------------------------------------------
  520. /**
  521. * Balances according to the AVL algorithm.
  522. */
  523. private AVLNode balance() {
  524. switch (heightRightMinusLeft()) {
  525. case 1 :
  526. case 0 :
  527. case -1 :
  528. return this;
  529. case -2 :
  530. if (left.heightRightMinusLeft() > 0) {
  531. setLeft(left.rotateLeft(), null);
  532. }
  533. return rotateRight();
  534. case 2 :
  535. if (right.heightRightMinusLeft() < 0) {
  536. setRight(right.rotateRight(), null);
  537. }
  538. return rotateLeft();
  539. default :
  540. throw new RuntimeException("tree inconsistent!");
  541. }
  542. }
  543. /**
  544. * Gets the relative position.
  545. */
  546. private int getOffset(AVLNode node) {
  547. if (node == null) {
  548. return 0;
  549. }
  550. return node.relativePosition;
  551. }
  552. /**
  553. * Sets the relative position.
  554. */
  555. private int setOffset(AVLNode node, int newOffest) {
  556. if (node == null) {
  557. return 0;
  558. }
  559. int oldOffset = getOffset(node);
  560. node.relativePosition = newOffest;
  561. return oldOffset;
  562. }
  563. /**
  564. * Sets the height by calculation.
  565. */
  566. private void recalcHeight() {
  567. height = Math.max(
  568. getLeftSubTree() == null ? -1 : getLeftSubTree().height,
  569. getRightSubTree() == null ? -1 : getRightSubTree().height) + 1;
  570. }
  571. /**
  572. * Returns the height of the node or -1 if the node is null.
  573. */
  574. private int getHeight(AVLNode node) {
  575. return (node == null ? -1 : node.height);
  576. }
  577. /**
  578. * Returns the height difference right - left
  579. */
  580. private int heightRightMinusLeft() {
  581. return getHeight(getRightSubTree()) - getHeight(getLeftSubTree());
  582. }
  583. private AVLNode rotateLeft() {
  584. AVLNode newTop = right; // can't be faedelung!
  585. AVLNode movedNode = getRightSubTree().getLeftSubTree();
  586. int newTopPosition = relativePosition + getOffset(newTop);
  587. int myNewPosition = -newTop.relativePosition;
  588. int movedPosition = getOffset(newTop) + getOffset(movedNode);
  589. setRight(movedNode, newTop);
  590. newTop.setLeft(this, null);
  591. setOffset(newTop, newTopPosition);
  592. setOffset(this, myNewPosition);
  593. setOffset(movedNode, movedPosition);
  594. return newTop;
  595. }
  596. private AVLNode rotateRight() {
  597. AVLNode newTop = left; // can't be faedelung
  598. AVLNode movedNode = getLeftSubTree().getRightSubTree();
  599. int newTopPosition = relativePosition + getOffset(newTop);
  600. int myNewPosition = -newTop.relativePosition;
  601. int movedPosition = getOffset(newTop) + getOffset(movedNode);
  602. setLeft(movedNode, newTop);
  603. newTop.setRight(this, null);
  604. setOffset(newTop, newTopPosition);
  605. setOffset(this, myNewPosition);
  606. setOffset(movedNode, movedPosition);
  607. return newTop;
  608. }
  609. private void setLeft(AVLNode node, AVLNode previous) {
  610. leftIsPrevious = (node == null);
  611. left = (leftIsPrevious ? previous : node);
  612. recalcHeight();
  613. }
  614. private void setRight(AVLNode node, AVLNode next) {
  615. rightIsNext = (node == null);
  616. right = (rightIsNext ? next : node);
  617. recalcHeight();
  618. }
  619. // private void checkFaedelung() {
  620. // AVLNode maxNode = left.max();
  621. // if (!maxNode.rightIsFaedelung || maxNode.right != this) {
  622. // throw new RuntimeException(maxNode + " should right-faedel to " + this);
  623. // }
  624. // AVLNode minNode = right.min();
  625. // if (!minNode.leftIsFaedelung || minNode.left != this) {
  626. // throw new RuntimeException(maxNode + " should left-faedel to " + this);
  627. // }
  628. // }
  629. //
  630. // private int checkTreeDepth() {
  631. // int hright = (getRightSubTree() == null ? -1 : getRightSubTree().checkTreeDepth());
  632. // // System.out.print("checkTreeDepth");
  633. // // System.out.print(this);
  634. // // System.out.print(" left: ");
  635. // // System.out.print(_left);
  636. // // System.out.print(" right: ");
  637. // // System.out.println(_right);
  638. //
  639. // int hleft = (left == null ? -1 : left.checkTreeDepth());
  640. // if (height != Math.max(hright, hleft) + 1) {
  641. // throw new RuntimeException(
  642. // "height should be max" + hleft + "," + hright + " but is " + height);
  643. // }
  644. // return height;
  645. // }
  646. //
  647. // private int checkLeftSubNode() {
  648. // if (getLeftSubTree() == null) {
  649. // return 0;
  650. // }
  651. // int count = 1 + left.checkRightSubNode();
  652. // if (left.relativePosition != -count) {
  653. // throw new RuntimeException();
  654. // }
  655. // return count + left.checkLeftSubNode();
  656. // }
  657. //
  658. // private int checkRightSubNode() {
  659. // AVLNode right = getRightSubTree();
  660. // if (right == null) {
  661. // return 0;
  662. // }
  663. // int count = 1;
  664. // count += right.checkLeftSubNode();
  665. // if (right.relativePosition != count) {
  666. // throw new RuntimeException();
  667. // }
  668. // return count + right.checkRightSubNode();
  669. // }
  670. /**
  671. * Used for debugging.
  672. */
  673. public String toString() {
  674. return "AVLNode(" + relativePosition + "," + (left != null) + "," + value +
  675. "," + (getRightSubTree() != null) + ", faedelung " + rightIsNext + " )";
  676. }
  677. }
  678. /**
  679. * A list iterator over the linked list.
  680. */
  681. static class TreeListIterator implements ListIterator, OrderedIterator {
  682. /** The parent list */
  683. protected final TreeList parent;
  684. /**
  685. * The node that will be returned by {@link #next()}. If this is equal
  686. * to {@link AbstractLinkedList#header} then there are no more values to return.
  687. */
  688. protected AVLNode next;
  689. /**
  690. * The index of {@link #next}.
  691. */
  692. protected int nextIndex;
  693. /**
  694. * The last node that was returned by {@link #next()} or {@link
  695. * #previous()}. Set to <code>null</code> if {@link #next()} or {@link
  696. * #previous()} haven't been called, or if the node has been removed
  697. * with {@link #remove()} or a new node added with {@link #add(Object)}.
  698. * Should be accessed through {@link #getLastNodeReturned()} to enforce
  699. * this behaviour.
  700. */
  701. protected AVLNode current;
  702. /**
  703. * The index of {@link #current}.
  704. */
  705. protected int currentIndex;
  706. /**
  707. * The modification count that the list is expected to have. If the list
  708. * doesn't have this count, then a
  709. * {@link java.util.ConcurrentModificationException} may be thrown by
  710. * the operations.
  711. */
  712. protected int expectedModCount;
  713. /**
  714. * Create a ListIterator for a list.
  715. *
  716. * @param parent the parent list
  717. * @param fromIndex the index to start at
  718. */
  719. protected TreeListIterator(TreeList parent, int fromIndex) throws IndexOutOfBoundsException {
  720. super();
  721. this.parent = parent;
  722. this.expectedModCount = parent.modCount;
  723. this.next = (parent.root == null ? null : parent.root.get(fromIndex));
  724. this.nextIndex = fromIndex;
  725. }
  726. /**
  727. * Checks the modification count of the list is the value that this
  728. * object expects.
  729. *
  730. * @throws ConcurrentModificationException If the list's modification
  731. * count isn't the value that was expected.
  732. */
  733. protected void checkModCount() {
  734. if (parent.modCount != expectedModCount) {
  735. throw new ConcurrentModificationException();
  736. }
  737. }
  738. public boolean hasNext() {
  739. return (nextIndex < parent.size());
  740. }
  741. public Object next() {
  742. checkModCount();
  743. if (!hasNext()) {
  744. throw new NoSuchElementException("No element at index " + nextIndex + ".");
  745. }
  746. if (next == null) {
  747. next = parent.root.get(nextIndex);
  748. }
  749. Object value = next.getValue();
  750. current = next;
  751. currentIndex = nextIndex++;
  752. next = next.next();
  753. return value;
  754. }
  755. public boolean hasPrevious() {
  756. return (nextIndex > 0);
  757. }
  758. public Object previous() {
  759. checkModCount();
  760. if (!hasPrevious()) {
  761. throw new NoSuchElementException("Already at start of list.");
  762. }
  763. if (next == null) {
  764. next = parent.root.get(nextIndex - 1);
  765. } else {
  766. next = next.previous();
  767. }
  768. Object value = next.getValue();
  769. current = next;
  770. currentIndex = --nextIndex;
  771. return value;
  772. }
  773. public int nextIndex() {
  774. return nextIndex;
  775. }
  776. public int previousIndex() {
  777. return nextIndex() - 1;
  778. }
  779. public void remove() {
  780. checkModCount();
  781. if (current == null) {
  782. throw new IllegalStateException();
  783. }
  784. parent.remove(currentIndex);
  785. current = null;
  786. currentIndex = -1;
  787. nextIndex--;
  788. expectedModCount++;
  789. }
  790. public void set(Object obj) {
  791. checkModCount();
  792. if (current == null) {
  793. throw new IllegalStateException();
  794. }
  795. current.setValue(obj);
  796. }
  797. public void add(Object obj) {
  798. checkModCount();
  799. parent.add(nextIndex, obj);
  800. current = null;
  801. currentIndex = -1;
  802. nextIndex++;
  803. expectedModCount++;
  804. }
  805. }
  806. }