PageRenderTime 46ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Java.NET/JavApi Commons collections (Apache Port)/org.apache.commons.collections.list.TreeList.cs

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