Firstly, the Iterator contract requires hasNext return true if there are more elements, and next will throw an exception if hasNext()==false .
This means that there are two styles of using the iterator: while (it.hasNext()) it.next() and try { while (true) it.next(); } catch ... try { while (true) it.next(); } catch ... The latter is not good practice, but it should be supported. I mentioned this because you cannot rely on hasNext , which was called before next . I found this requirement, as a rule, the culprit of unnecessary complexity in the implementation of iterators.
My choice has a local variable with the value next . If next==null either the next value is unknown (and we must find it), or we have reached the end of the iteration ( hasNext() will return false and next() will fail). Consider also that when the next value is unknown, it is possible that we are at the end of the iteration, but we have not realized this yet.
Node next; public boolean hasNext() { //if the next value already known, do nothing if (next==null) { //otherwise lookup the next value next=findNext(); } //return true if the next value was found return next!=null; } public Node next() { if (next==null&&!hasNext()) { //here we have reached the end of the iteration throw new NoSuchElementException(); } else { //either we alredy knowed the next element //or it was found by hasNext Node result = next; next=null; return result; } } private Node findNext() { //the actual iteration }
About the traversal case in order, you should keep the stack (note that the Stack implementation is array-based and synchronized, it is best to use Dequeue , such as LinkedList , which also supports push and pop in Java 6) and an auxiliary state in order to know how to resume iteration every time findNext is findNext .
source share