KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > list > TreeList


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
18 import java.util.AbstractList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.ConcurrentModificationException JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.ListIterator JavaDoc;
23 import java.util.NoSuchElementException JavaDoc;
24
25 import org.apache.commons.collections.OrderedIterator;
26
27 /**
28  * A <code>List</code> implementation that is optimised for fast insertions and
29  * removals at any index in the list.
30  * <p>
31  * This list implementation utilises a tree structure internally to ensure that
32  * all insertions and removals are O(log n). This provides much faster performance
33  * than both an <code>ArrayList</code> and a <code>LinkedList</code> where elements
34  * are inserted and removed repeatedly from anywhere in the list.
35  * <p>
36  * The following relative performance statistics are indicative of this class:
37  * <pre>
38  * get add insert iterate remove
39  * TreeList 3 5 1 2 1
40  * ArrayList 1 1 40 1 40
41  * LinkedList 5800 1 350 2 325
42  * </pre>
43  * <code>ArrayList</code> is a good general purpose list implementation.
44  * It is faster than <code>TreeList</code> for most operations except inserting
45  * and removing in the middle of the list. <code>ArrayList</code> also uses less
46  * memory as <code>TreeList</code> uses one object per entry.
47  * <p>
48  * <code>LinkedList</code> is rarely a good choice of implementation.
49  * <code>TreeList</code> is almost always a good replacement for it, although it
50  * does use sligtly more memory.
51  *
52  * @since Commons Collections 3.1
53  * @version $Revision: 1.3 $ $Date: 2004/05/26 21:56:05 $
54  *
55  * @author Joerg Schmuecker
56  * @author Stephen Colebourne
57  */

58 public class TreeList extends AbstractList JavaDoc {
59 // add; toArray; iterator; insert; get; indexOf; remove
60
// TreeList = 1260;7360;3080; 160; 170;3400; 170;
61
// ArrayList = 220;1480;1760; 6870; 50;1540; 7200;
62
// LinkedList = 270;7360;3350;55860;290720;2910;55200;
63

64     /** The root node in the AVL tree */
65     private AVLNode root;
66
67     /** The current size of the list */
68     private int size;
69
70     //-----------------------------------------------------------------------
71
/**
72      * Constructs a new empty list.
73      */

74     public TreeList() {
75         super();
76     }
77
78     /**
79      * Constructs a new empty list that copies the specified list.
80      *
81      * @param coll the collection to copy
82      * @throws NullPointerException if the collection is null
83      */

84     public TreeList(Collection JavaDoc coll) {
85         super();
86         addAll(coll);
87     }
88
89     //-----------------------------------------------------------------------
90
/**
91      * Gets the element at the specified index.
92      *
93      * @param index the index to retrieve
94      * @return the element at the specified index
95      */

96     public Object JavaDoc get(int index) {
97         checkInterval(index, 0, size() - 1);
98         return root.get(index).getValue();
99     }
100
101     /**
102      * Gets the current size of the list.
103      *
104      * @return the current size
105      */

106     public int size() {
107         return size;
108     }
109
110     /**
111      * Gets an iterator over the list.
112      *
113      * @return an iterator over the list
114      */

115     public Iterator JavaDoc iterator() {
116         // override to go 75% faster
117
return listIterator(0);
118     }
119
120     /**
121      * Gets a ListIterator over the list.
122      *
123      * @return the new iterator
124      */

125     public ListIterator JavaDoc listIterator() {
126         // override to go 75% faster
127
return listIterator(0);
128     }
129
130     /**
131      * Gets a ListIterator over the list.
132      *
133      * @param fromIndex the index to start from
134      * @return the new iterator
135      */

136     public ListIterator JavaDoc listIterator(int fromIndex) {
137         // override to go 75% faster
138
// cannot use EmptyIterator as iterator.add() must work
139
checkInterval(fromIndex, 0, size());
140         return new TreeListIterator(this, fromIndex);
141     }
142
143     /**
144      * Searches for the index of an object in the list.
145      *
146      * @return the index of the object, -1 if not found
147      */

148     public int indexOf(Object JavaDoc object) {
149         // override to go 75% faster
150
if (root == null) {
151             return -1;
152         }
153         return root.indexOf(object, root.relativePosition);
154     }
155
156     /**
157      * Searches for the presence of an object in the list.
158      *
159      * @return true if the object is found
160      */

161     public boolean contains(Object JavaDoc object) {
162         return (indexOf(object) >= 0);
163     }
164
165     /**
166      * Converts the list into an array.
167      *
168      * @return the list as an array
169      */

170     public Object JavaDoc[] toArray() {
171         // override to go 20% faster
172
Object JavaDoc[] array = new Object JavaDoc[size()];
173         if (root != null) {
174             root.toArray(array, root.relativePosition);
175         }
176         return array;
177     }
178
179     //-----------------------------------------------------------------------
180
/**
181      * Adds a new element to the list.
182      *
183      * @param index the index to add before
184      * @param obj the element to add
185      */

186     public void add(int index, Object JavaDoc obj) {
187         modCount++;
188         checkInterval(index, 0, size());
189         if (root == null) {
190             root = new AVLNode(index, obj, null, null);
191         } else {
192             root = root.insert(index, obj);
193         }
194         size++;
195     }
196
197     /**
198      * Sets the element at the specified index.
199      *
200      * @param index the index to set
201      * @param obj the object to store at the specified index
202      * @return the previous object at that index
203      * @throws IndexOutOfBoundsException if the index is invalid
204      */

205     public Object JavaDoc set(int index, Object JavaDoc obj) {
206         checkInterval(index, 0, size() - 1);
207         AVLNode node = root.get(index);
208         Object JavaDoc result = node.value;
209         node.setValue(obj);
210         return result;
211     }
212
213     /**
214      * Removes the element at the specified index.
215      *
216      * @param index the index to remove
217      * @return the previous object at that index
218      */

219     public Object JavaDoc remove(int index) {
220         modCount++;
221         checkInterval(index, 0, size() - 1);
222         Object JavaDoc result = get(index);
223         root = root.remove(index);
224         size--;
225         return result;
226     }
227
228     /**
229      * Clears the list, removing all entries.
230      */

231     public void clear() {
232         modCount++;
233         root = null;
234         size = 0;
235     }
236
237     //-----------------------------------------------------------------------
238
/**
239      * Checks whether the index is valid.
240      *
241      * @param index the index to check
242      * @param startIndex the first allowed index
243      * @param endIndex the last allowed index
244      * @throws IndexOutOfBoundsException if the index is invalid
245      */

246     private void checkInterval(int index, int startIndex, int endIndex) {
247         if (index < startIndex || index > endIndex) {
248             throw new IndexOutOfBoundsException JavaDoc("Invalid index:" + index + ", size=" + size());
249         }
250     }
251
252     //-----------------------------------------------------------------------
253
/**
254      * Implements an AVLNode which keeps the offset updated.
255      * <p>
256      * This node contains the real work.
257      * TreeList is just there to implement {@link java.util.List}.
258      * The nodes don't know the index of the object they are holding. They
259      * do know however their position relative to their parent node.
260      * This allows to calculate the index of a node while traversing the tree.
261      * <p>
262      * The Faedelung calculation stores a flag for both the left and right child
263      * to indicate if they are a child (false) or a link as in linked list (true).
264      */

265     static class AVLNode {
266         /** The left child node or the predecessor if {@link #leftIsPrevious}.*/
267         private AVLNode left;
268         /** Flag indicating that left reference is not a subtree but the predecessor. */
269         private boolean leftIsPrevious;
270         /** The right child node or the successor if {@link #rightIsNext}. */
271         private AVLNode right;
272         /** Flag indicating that right reference is not a subtree but the successor. */
273         private boolean rightIsNext;
274         /** How many levels of left/right are below this one. */
275         private int height;
276         /** The relative position, root holds absolute position. */
277         private int relativePosition;
278         /** The stored element. */
279         private Object JavaDoc value;
280
281         /**
282          * Constructs a new node with a relative position.
283          *
284          * @param relativePosition the relative position of the node
285          * @param obj the value for the ndoe
286          * @param rightFollower the node with the value following this one
287          * @param leftFollower the node with the value leading this one
288          */

289         private AVLNode(int relativePosition, Object JavaDoc obj, AVLNode rightFollower, AVLNode leftFollower) {
290             this.relativePosition = relativePosition;
291             value = obj;
292             rightIsNext = true;
293             leftIsPrevious = true;
294             right = rightFollower;
295             left = leftFollower;
296         }
297
298         /**
299          * Gets the value.
300          *
301          * @return the value of this node
302          */

303         Object JavaDoc getValue() {
304             return value;
305         }
306
307         /**
308          * Sets the value.
309          *
310          * @param obj the value to store
311          */

312         void setValue(Object JavaDoc obj) {
313             this.value = obj;
314         }
315
316         /**
317          * Locate the element with the given index relative to the
318          * offset of the parent of this node.
319          */

320         AVLNode get(int index) {
321             int indexRelativeToMe = index - relativePosition;
322
323             if (indexRelativeToMe == 0) {
324                 return this;
325             }
326
327             AVLNode nextNode = ((indexRelativeToMe < 0) ? getLeftSubTree() : getRightSubTree());
328             if (nextNode == null) {
329                 return null;
330             }
331             return nextNode.get(indexRelativeToMe);
332         }
333
334         /**
335          * Locate the index that contains the specified object.
336          */

337         int indexOf(Object JavaDoc object, int index) {
338             if (getLeftSubTree() != null) {
339                 int result = left.indexOf(object, index + left.relativePosition);
340                 if (result != -1) {
341                     return result;
342                 }
343             }
344             if (value == null ? value == object : value.equals(object)) {
345                 return index;
346             }
347             if (getRightSubTree() != null) {
348                 return right.indexOf(object, index + right.relativePosition);
349             }
350             return -1;
351         }
352
353         /**
354          * Stores the node and its children into the array specified.
355          *
356          * @param array the array to be filled
357          * @param index the index of this node
358          */

359         void toArray(Object JavaDoc[] array, int index) {
360             array[index] = value;
361             if (getLeftSubTree() != null) {
362                 left.toArray(array, index + left.relativePosition);
363             }
364             if (getRightSubTree() != null) {
365                 right.toArray(array, index + right.relativePosition);
366             }
367         }
368
369         /**
370          * Gets the next node in the list after this one.
371          *
372          * @return the next node
373          */

374         AVLNode next() {
375             if (rightIsNext || right == null) {
376                 return right;
377             }
378             return right.min();
379         }
380
381         /**
382          * Gets the node in the list before this one.
383          *
384          * @return the previous node
385          */

386         AVLNode previous() {
387             if (leftIsPrevious || left == null) {
388                 return left;
389             }
390             return left.max();
391         }
392
393         /**
394          * Inserts a node at the position index.
395          *
396          * @param index is the index of the position relative to the position of
397          * the parent node.
398          * @param obj is the object to be stored in the position.
399          */

400         AVLNode insert(int index, Object JavaDoc obj) {
401             int indexRelativeToMe = index - relativePosition;
402
403             if (indexRelativeToMe <= 0) {
404                 return insertOnLeft(indexRelativeToMe, obj);
405             } else {
406                 return insertOnRight(indexRelativeToMe, obj);
407             }
408         }
409
410         private AVLNode insertOnLeft(int indexRelativeToMe, Object JavaDoc obj) {
411             AVLNode ret = this;
412
413             if (getLeftSubTree() == null) {
414                 setLeft(new AVLNode(-1, obj, this, left), null);
415             } else {
416                 setLeft(left.insert(indexRelativeToMe, obj), null);
417             }
418
419             if (relativePosition >= 0) {
420                 relativePosition++;
421             }
422             ret = balance();
423             recalcHeight();
424             return ret;
425         }
426
427         private AVLNode insertOnRight(int indexRelativeToMe, Object JavaDoc obj) {
428             AVLNode ret = this;
429
430             if (getRightSubTree() == null) {
431                 setRight(new AVLNode(+1, obj, right, this), null);
432             } else {
433                 setRight(right.insert(indexRelativeToMe, obj), null);
434             }
435             if (relativePosition < 0) {
436                 relativePosition--;
437             }
438             ret = balance();
439             recalcHeight();
440             return ret;
441         }
442
443         //-----------------------------------------------------------------------
444
/**
445          * Gets the left node, returning null if its a faedelung.
446          */

447         private AVLNode getLeftSubTree() {
448             return (leftIsPrevious ? null : left);
449         }
450
451         /**
452          * Gets the right node, returning null if its a faedelung.
453          */

454         private AVLNode getRightSubTree() {
455             return (rightIsNext ? null : right);
456         }
457
458         /**
459          * Gets the rightmost child of this node.
460          *
461          * @return the rightmost child (greatest index)
462          */

463         private AVLNode max() {
464             return (getRightSubTree() == null) ? this : right.max();
465         }
466
467         /**
468          * Gets the leftmost child of this node.
469          *
470          * @return the leftmost child (smallest index)
471          */

472         private AVLNode min() {
473             return (getLeftSubTree() == null) ? this : left.min();
474         }
475
476         /**
477          * Removes the node at a given position.
478          *
479          * @param index is the index of the element to be removed relative to the position of
480          * the parent node of the current node.
481          */

482         AVLNode remove(int index) {
483             int indexRelativeToMe = index - relativePosition;
484
485             if (indexRelativeToMe == 0) {
486                 return removeSelf();
487             }
488             if (indexRelativeToMe > 0) {
489                 setRight(right.remove(indexRelativeToMe), right.right);
490                 if (relativePosition < 0) {
491                     relativePosition++;
492                 }
493             } else {
494                 setLeft(left.remove(indexRelativeToMe), left.left);
495                 if (relativePosition > 0) {
496                     relativePosition--;
497                 }
498             }
499             recalcHeight();
500             return balance();
501         }
502
503         private AVLNode removeMax() {
504             if (getRightSubTree() == null) {
505                 return removeSelf();
506             }
507             setRight(right.removeMax(), right.right);
508             if (relativePosition < 0) {
509                 relativePosition++;
510             }
511             recalcHeight();
512             return balance();
513         }
514
515         private AVLNode removeMin() {
516             if (getLeftSubTree() == null) {
517                 return removeSelf();
518             }
519             setLeft(left.removeMin(), left.left);
520             if (relativePosition > 0) {
521                 relativePosition--;
522             }
523             recalcHeight();
524             return balance();
525         }
526
527         private AVLNode removeSelf() {
528             if (getRightSubTree() == null && getLeftSubTree() == null)
529                 return null;
530             if (getRightSubTree() == null) {
531                 if (relativePosition > 0) {
532                     left.relativePosition += relativePosition + (relativePosition > 0 ? 0 : 1);
533                 }
534                 left.max().setRight(null, right);
535                 return left;
536             }
537             if (getLeftSubTree() == null) {
538                 right.relativePosition += relativePosition - (relativePosition < 0 ? 0 : 1);
539                 right.min().setLeft(null, left);
540                 return right;
541             }
542
543             if (heightRightMinusLeft() > 0) {
544                 AVLNode rightMin = right.min();
545                 value = rightMin.value;
546                 if (leftIsPrevious) {
547                     left = rightMin.left;
548                 }
549                 right = right.removeMin();
550                 if (relativePosition < 0) {
551                     relativePosition++;
552                 }
553             } else {
554                 AVLNode leftMax = left.max();
555                 value = leftMax.value;
556                 if (rightIsNext) {
557                     right = leftMax.right;
558                 }
559                 left = left.removeMax();
560                 if (relativePosition > 0) {
561                     relativePosition--;
562                 }
563             }
564             recalcHeight();
565             return this;
566         }
567
568         //-----------------------------------------------------------------------
569
/**
570          * Balances according to the AVL algorithm.
571          */

572         private AVLNode balance() {
573             switch (heightRightMinusLeft()) {
574                 case 1 :
575                 case 0 :
576                 case -1 :
577                     return this;
578                 case -2 :
579                     if (left.heightRightMinusLeft() > 0) {
580                         setLeft(left.rotateLeft(), null);
581                     }
582                     return rotateRight();
583                 case 2 :
584                     if (right.heightRightMinusLeft() < 0) {
585                         setRight(right.rotateRight(), null);
586                     }
587                     return rotateLeft();
588                 default :
589                     throw new RuntimeException JavaDoc("tree inconsistent!");
590             }
591         }
592
593         /**
594          * Gets the relative position.
595          */

596         private int getOffset(AVLNode node) {
597             if (node == null) {
598                 return 0;
599             }
600             return node.relativePosition;
601         }
602
603         /**
604          * Sets the relative position.
605          */

606         private int setOffset(AVLNode node, int newOffest) {
607             if (node == null) {
608                 return 0;
609             }
610             int oldOffset = getOffset(node);
611             node.relativePosition = newOffest;
612             return oldOffset;
613         }
614
615         /**
616          * Sets the height by calculation.
617          */

618         private void recalcHeight() {
619             height = Math.max(
620                 getLeftSubTree() == null ? -1 : getLeftSubTree().height,
621                 getRightSubTree() == null ? -1 : getRightSubTree().height) + 1;
622         }
623
624         /**
625          * Returns the height of the node or -1 if the node is null.
626          */

627         private int getHeight(AVLNode node) {
628             return (node == null ? -1 : node.height);
629         }
630
631         /**
632          * Returns the height difference right - left
633          */

634         private int heightRightMinusLeft() {
635             return getHeight(getRightSubTree()) - getHeight(getLeftSubTree());
636         }
637
638         private AVLNode rotateLeft() {
639             AVLNode newTop = right; // can't be faedelung!
640
AVLNode movedNode = getRightSubTree().getLeftSubTree();
641
642             int newTopPosition = relativePosition + getOffset(newTop);
643             int myNewPosition = -newTop.relativePosition;
644             int movedPosition = getOffset(newTop) + getOffset(movedNode);
645
646             setRight(movedNode, newTop);
647             newTop.setLeft(this, null);
648
649             setOffset(newTop, newTopPosition);
650             setOffset(this, myNewPosition);
651             setOffset(movedNode, movedPosition);
652             return newTop;
653         }
654
655         private AVLNode rotateRight() {
656             AVLNode newTop = left; // can't be faedelung
657
AVLNode movedNode = getLeftSubTree().getRightSubTree();
658
659             int newTopPosition = relativePosition + getOffset(newTop);
660             int myNewPosition = -newTop.relativePosition;
661             int movedPosition = getOffset(newTop) + getOffset(movedNode);
662
663             setLeft(movedNode, newTop);
664             newTop.setRight(this, null);
665
666             setOffset(newTop, newTopPosition);
667             setOffset(this, myNewPosition);
668             setOffset(movedNode, movedPosition);
669             return newTop;
670         }
671
672         private void setLeft(AVLNode node, AVLNode previous) {
673             leftIsPrevious = (node == null);
674             left = (leftIsPrevious ? previous : node);
675             recalcHeight();
676         }
677
678         private void setRight(AVLNode node, AVLNode next) {
679             rightIsNext = (node == null);
680             right = (rightIsNext ? next : node);
681             recalcHeight();
682         }
683
684 // private void checkFaedelung() {
685
// AVLNode maxNode = left.max();
686
// if (!maxNode.rightIsFaedelung || maxNode.right != this) {
687
// throw new RuntimeException(maxNode + " should right-faedel to " + this);
688
// }
689
// AVLNode minNode = right.min();
690
// if (!minNode.leftIsFaedelung || minNode.left != this) {
691
// throw new RuntimeException(maxNode + " should left-faedel to " + this);
692
// }
693
// }
694
//
695
// private int checkTreeDepth() {
696
// int hright = (getRightSubTree() == null ? -1 : getRightSubTree().checkTreeDepth());
697
// // System.out.print("checkTreeDepth");
698
// // System.out.print(this);
699
// // System.out.print(" left: ");
700
// // System.out.print(_left);
701
// // System.out.print(" right: ");
702
// // System.out.println(_right);
703
//
704
// int hleft = (left == null ? -1 : left.checkTreeDepth());
705
// if (height != Math.max(hright, hleft) + 1) {
706
// throw new RuntimeException(
707
// "height should be max" + hleft + "," + hright + " but is " + height);
708
// }
709
// return height;
710
// }
711
//
712
// private int checkLeftSubNode() {
713
// if (getLeftSubTree() == null) {
714
// return 0;
715
// }
716
// int count = 1 + left.checkRightSubNode();
717
// if (left.relativePosition != -count) {
718
// throw new RuntimeException();
719
// }
720
// return count + left.checkLeftSubNode();
721
// }
722
//
723
// private int checkRightSubNode() {
724
// AVLNode right = getRightSubTree();
725
// if (right == null) {
726
// return 0;
727
// }
728
// int count = 1;
729
// count += right.checkLeftSubNode();
730
// if (right.relativePosition != count) {
731
// throw new RuntimeException();
732
// }
733
// return count + right.checkRightSubNode();
734
// }
735

736         /**
737          * Used for debugging.
738          */

739         public String JavaDoc toString() {
740             return "AVLNode(" + relativePosition + "," + (left != null) + "," + value +
741                 "," + (getRightSubTree() != null) + ", faedelung " + rightIsNext + " )";
742         }
743     }
744
745     /**
746      * A list iterator over the linked list.
747      */

748     static class TreeListIterator implements ListIterator JavaDoc, OrderedIterator {
749         /** The parent list */
750         protected final TreeList parent;
751         /**
752          * The node that will be returned by {@link #next()}. If this is equal
753          * to {@link AbstractLinkedList#header} then there are no more values to return.
754          */

755         protected AVLNode next;
756         /**
757          * The index of {@link #next}.
758          */

759         protected int nextIndex;
760         /**
761          * The last node that was returned by {@link #next()} or {@link
762          * #previous()}. Set to <code>null</code> if {@link #next()} or {@link
763          * #previous()} haven't been called, or if the node has been removed
764          * with {@link #remove()} or a new node added with {@link #add(Object)}.
765          * Should be accessed through {@link #getLastNodeReturned()} to enforce
766          * this behaviour.
767          */

768         protected AVLNode current;
769         /**
770          * The index of {@link #current}.
771          */

772         protected int currentIndex;
773         /**
774          * The modification count that the list is expected to have. If the list
775          * doesn't have this count, then a
776          * {@link java.util.ConcurrentModificationException} may be thrown by
777          * the operations.
778          */

779         protected int expectedModCount;
780
781         /**
782          * Create a ListIterator for a list.
783          *
784          * @param parent the parent list
785          * @param fromIndex the index to start at
786          */

787         protected TreeListIterator(TreeList parent, int fromIndex) throws IndexOutOfBoundsException JavaDoc {
788             super();
789             this.parent = parent;
790             this.expectedModCount = parent.modCount;
791             this.next = (parent.root == null ? null : parent.root.get(fromIndex));
792             this.nextIndex = fromIndex;
793         }
794
795         /**
796          * Checks the modification count of the list is the value that this
797          * object expects.
798          *
799          * @throws ConcurrentModificationException If the list's modification
800          * count isn't the value that was expected.
801          */

802         protected void checkModCount() {
803             if (parent.modCount != expectedModCount) {
804                 throw new ConcurrentModificationException JavaDoc();
805             }
806         }
807
808         public boolean hasNext() {
809             return (nextIndex < parent.size());
810         }
811
812         public Object JavaDoc next() {
813             checkModCount();
814             if (!hasNext()) {
815                 throw new NoSuchElementException JavaDoc("No element at index " + nextIndex + ".");
816             }
817             if (next == null) {
818                 next = parent.root.get(nextIndex);
819             }
820             Object JavaDoc value = next.getValue();
821             current = next;
822             currentIndex = nextIndex++;
823             next = next.next();
824             return value;
825         }
826
827         public boolean hasPrevious() {
828             return (nextIndex > 0);
829         }
830
831         public Object JavaDoc previous() {
832             checkModCount();
833             if (!hasPrevious()) {
834                 throw new NoSuchElementException JavaDoc("Already at start of list.");
835             }
836             if (next == null) {
837                 next = parent.root.get(nextIndex - 1);
838             } else {
839                 next = next.previous();
840             }
841             Object JavaDoc value = next.getValue();
842             current = next;
843             currentIndex = --nextIndex;
844             return value;
845         }
846
847         public int nextIndex() {
848             return nextIndex;
849         }
850
851         public int previousIndex() {
852             return nextIndex() - 1;
853         }
854
855         public void remove() {
856             checkModCount();
857             if (current == null) {
858                 throw new IllegalStateException JavaDoc();
859             }
860             parent.remove(currentIndex);
861             current = null;
862             currentIndex = -1;
863             nextIndex--;
864             expectedModCount++;
865         }
866
867         public void set(Object JavaDoc obj) {
868             checkModCount();
869             if (current == null) {
870                 throw new IllegalStateException JavaDoc();
871             }
872             current.setValue(obj);
873         }
874
875         public void add(Object JavaDoc obj) {
876             checkModCount();
877             parent.add(nextIndex, obj);
878             current = null;
879             currentIndex = -1;
880             nextIndex++;
881             expectedModCount++;
882         }
883     }
884
885 }
886
Popular Tags