Lecture 20: Iterators

Iterators are discussed in DJW pps. 396-397, but this is so short as to be useless. Note: This material will not be on the assignments or the exam

Iterators in Java library classes e.g. LinkedList

We did this in lecture 6, but just to remind you:

Java library list classes

LL1.java

Iterator is an interface with methods hasNext() and next().
hasNext() is a boolean which is true if the collection has more elements to iterate over.
next() returns the next item and advances the iterator.
Note that next() always advances the iterator; if you need an element in the collection more than once, you have to save it in a variable.

Three ways to use an iterator

Iterators and the "for each" construction are defined in any class that implements the Iterable interface.

Note that an understanding of iterators is built into the Java syntax, so in that sense a fundamental part of the language.

Defining your own Iterators

From here down, things get a little strange. On the other hand, this opens up a whole new way of constructing programs.

In Lecture notes 10 we defined a generic tree class: Tree.java

Here we write an iterator for the children of a given node for Trees of Strings. (You would think this could be done generically, for Trees of labels of type T, but that seems to hopelessly confuse the compiler.) StringTreeIterateChild.java

The structures here uses some advanced Java features that I'm not going to discuss. If you want to do this, copy the code from somewhere that has it right (e.g. here) and modify.

The method iterator() is defined. It returns an Iterator < Tree < String >>

It has local variable. Note particularly variable c that keeps track of its place in the list of children.

There are three methods defined within iterator(): hasNext(), next() and remove. The interface Iterator requires that you have these. We have left remove a no-op.

The variable c is used to keep track of the place of the iterator in the tree. It is initialized to TreeIteratePreorder.this, meaning the tree that is being iterated over. If we just wrote this, it would assume that that means the iterator itself, which would give a compiler error.

Note the semi-colon after the close bracket on line 37. That is to end the large assignment statement that begins on line 13; ic is being assigned an anonymous class as a value.

The main method creates a ternary tree of depth 3, and then prints out the children of the root and then the childent of the first grandchild of the root.

Another example: TreeIteratePreorder.java

This iterator returns the labels in a generic tree Tree in preorder sequence.

It uses the method preorderNext() which finds the next node in preorder by climbing down and up.

    if there is a child, 
       go to the first child
    otherwise
       go to the first ancestor (including self) that has a nextSibling
       go to that nextSibling

You can even have iterators that just return next() values that they make up on the fly, rather than taking out of an actual data structure. For instance

RepeatString.java creates an iterator that takes a string w as argument and first returns w, then w+w, then w+w+w, etc. as long as you want new values.

TwoFingeredIntersect.java implements a generic two-fingered over any classes U and V that are Iterable < T >'s. where T itself is a Comparable

TestTwoFingered.java test the two-fingered interface by computing the intersection of a TreeIteratePreorder with an ArrayList and with a RepeatString.