CS 635: Advanced Object-Oriented Design & Programming |
---|
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 |
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() );
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"); } }
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!
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" ); }
Vector listOfStudents = new Vector(); // code to add students not shown VectorIterator list = new VectorIterator( listOfStudents ); while ( list.hasMoreElements() ) Console.println( list.nextElement() );
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 }
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 );
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
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() );
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; } }
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") ]);
Java 1.2 adds an Iterator class
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
See the NullObject pattern