SDSU CS 635: Advanced Object-Oriented Design & Programming
Spring Semester, 1998
Iterator

To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 21-Apr-98

Contents of Doc 18, Iterator


Iterator slide # 2
...Concrete vs. Polymorphic Iterators slide # 4
...Using A Smart Pointer to avoid Memory Leaks slide # 5
...Who Controls the iteration? slide # 6
...Who Defines the Traversal Algorithm? slide # 8
...How robust is the iterator? slide # 9
...Additional Iterator Operations slide # 9
...Iterators and Privileged Access slide # 13
...Iterators for Composites slide # 13
...NullIterator slide # 13




Doc 18, Iterator Slide # 2

Iterator


Provides a way to access elements of an aggregate object sequentially without exposing its underlying representation

Java Examples

Vector listOfStudents = new Vector();

// code to add students not shown

Enumeration list = listOfStudents.elements();

while ( list.hasMoreElements() )
     Console.println( list.nextElement() );
     
Hashtable anIndex = new Hashtable();
// code to add elements to the hashtable not shown

Enumeration list = anIndex.keys();

while ( list.hasMoreElements() )
     Console.println( list.nextElement() );


Doc 18, Iterator Slide # 3
Sample Implementation of Java Enumerator

class VectorIterator implements Enumeration {
     Vector iteratee;
     int count;

     VectorIterator(Vector v) {
          iteratee = v;
          count = 0;
     }

     public boolean hasMoreElements() {
          return count < iteratee.elementCount;
     }

     public Object nextElement() {
          synchronized (iteratee) {
               if (count < iteratee.elementCount) 
                    return iteratee.elementData[count++];
          }
     throw new NoSuchElementException("VectorIterator");
     }
}

Note the iterators using privileged access to Vectors fields


Doc 18, Iterator Slide # 4
Issues

Concrete vs. Polymorphic Iterators


Concrete - Use Explicit Iterator Type

Vector listOfStudents = new Vector();

// code to add students not shown

VectorIterator list = new VectorIterator( listOfStudents );

while ( list.hasMoreElements() )
     Console.println( list.nextElement() );


Polymorphic

Vector listOfStudents = new Vector();

// code to add students not shown

// Note use of factory method to get iterator

Enumeration list = listOfStudents.elements();

while ( list.hasMoreElements() )
     Console.println( list.nextElement() );


Polymorphic iterators can cause problems with memory leaks in C++ because they are on the heap!


Doc 18, Iterator Slide # 5

Using A Smart Pointer to avoid Memory Leaks


template <class Item>
class SmartPointer
     {
     public:
          SmartPointer( <Item>* aPointee );
          ~SmartPointer( ) 
               { delete pointee; }
               
          <Item>* operator->() 
               { return pointee; }
          
          <Item>& operator*()
               { return *pointee; }
     
     private:
          // Can not allow multiple copies of pointee
          // hide copy and assignment
          SmartPointer( const SmartPointer& );
          SmartPointer& operator=(const 
SmartPointer& );
          
          <Item>* pointee;
     }
     
void sample()
     {
     SmartPointer safe( new Vector() );
     safe->append( "This should work" );
     }


Doc 18, Iterator Slide # 6

Who Controls the iteration?

External (Active)

Vector listOfStudents = new Vector();

// code to add students not shown

VectorIterator list = new VectorIterator( listOfStudents );

while ( list.hasMoreElements() )
     Console.println( list.nextElement() );



Doc 18, Iterator Slide # 7
Who Controls the iteration?
Internal (Passive)

Vector listOfStudents = new Vector();

// code to add students not shown

while ( listOfStudents.hasMoreElements() )
     Console.println( listOfStudents.nextElement() );

class Vector implements Cloneable, java.io.Serializable {
     protected Object elementData[];
     protected int elementCount;
     protected int currentPosition;
     
     public boolean hasMoreElements() {
          return currentPosition < elementCount;
     }

     public Object nextElement() {
          if (currentPosition < elementCount) 
               return elementData[currentPosition++];
     throw new NoSuchElementException("VectorIterator");
     }
     
     // all vector methods not shown

}


Doc 18, Iterator Slide # 8

Who Defines the Traversal Algorithm?

Object being Iterated

Iterator can store where we are

In a Vector this could mean the index of the current item

In a tree structure it could mean a pointer to current node and stack of past nodes

BinaryTree searchTree = new BinaryTree();

// code to add items not shown

Iterator aSearch = searchTree.getIterator();
Iterator bSearch = searchTree.getIterator();
Object first = searchTree.nextElement( aSearch );
Object stillFirst = searchTree.nextElement( bSearch );

Iterator

Makes it easier to have multiple iterator algorithms on same type

On Vector class, why not have a reverseIterator which goes backwards?

In a complex structure the iterator may need access to the iteratee's implementation


Doc 18, Iterator Slide # 9

How robust is the iterator?


What happens when items are added/removed from the iteratee while an iterator exists?

Vector listOfStudents = new Vector();

// code to add students not shown

VectorIterator list = new VectorIterator( listOfStudents );

list.removeElementAt( 5 );

while ( list.hasMoreElements() )
     Console.println( list.nextElement() );

Additional Iterator Operations


previous()
back up one location
add( Object item)
add item to the iteratee at current location
remove()
remove the current item from the iteratee
skipTo( some location, item or condition )
go to the location indicated
mark()
mark current location for future return

Doc 18, Iterator Slide # 10
Example of Additional Iterator Operations

class SelectIterator
     {
     Enumeration iteratee;
     
     public SelectionIterator( Vector newIteratee )
          {
          iteratee = newIteratee.elements();
          }
     
     public select( Command condition )
          {
          Vector selected = new Vector();
          
          while ( iteratee.hasMoreElements() )
               {
               Object candidate = iteratee.nextElement();
               if ( condition.execute( candidate ) )
                    selected.addElement( candidate )
               }
          return selected;
          }
     }


Doc 18, Iterator Slide # 11
class StringContains extends Command
     {
     String searchString;
     public StringContains( String aString )
          {
          searchString = aString;
          }
     
     public boolean execute( Object aString )
          {
          return ((String) aString)).contains( searchString );
          }
     }


Vector studentList = new Vector();
// code adding student not shown

SelectionIterator findName = new SelectionIterator( studentList );

Vector theBills = findName.select( new StringContains( "bill" ) );
Vector theJoses = findName.select( new StringContains( "jose" )
);

Smalltalk Equivalent of Entire Example
Vector studentList = new Vector();
// code adding student not shown

Vector theBills, theJoses;
theBills = studentList.select( [ ( x ) | return x.contains("bill") ]);
theJoses = studentList.select( [ ( x ) | return x.contains("jose") ]);

Doc 18, Iterator Slide # 12
Java, Enumeration and Iterators

Java's enumeration class is a bare minimum iterator

Java 1.2 adds an Iterator class

Iterator Operations
hasNext()
Returns true if the iteration has more elements.
next()
Returns the next element in the interation.
remove()
Removes from the underlying Collection the last element returned by the Iterator .

ListIterator extend Iterator

add(Object)
Inserts the specified element into the List.
hasNext()
Returns true if this ListIterator has more elements when traversing the list in the forward direction.
hasPrevious()
Returns true if this ListIterator has more elements when traversing the list in the reverse direction.
next()
Returns the next element in the List.
nextIndex()
Returns the index of the element that would be returned by a subsequent call to next.
previous()
Returns the previous element in the List.
previousIndex()
Returns the index of the element that would be returned by a subsequent call to previous.
remove()
Removes from the List the last element that was returned by next or previous.
set(Object)
Replaces the last element returned by next or previous with the specified element.

Doc 18, Iterator Slide # 13

Iterators and Privileged Access


An iterator may need privileged access to the aggregate structure for traversal


Iterators for Composites


Traversing a complex structure like a graph, tree, or composite can be difficult

An internal iterator can use recursion to keep track of where to go next

For example using a depth-first search algorithm on graph

If each element in the aggregate "knows" how to traverse to the next element and previous element, than an external iterator can be used


NullIterator


A Null iterator for the empty aggregates can be useful

See the NullObject pattern


visitors since 24-Mar-98