Iterators

advertisement
Iterators
CS 367 – Introduction to Data Structures
Iterator
• Allows a user to step through each item in
a data structure
– array, vector, linked list, tree, etc.
• Two basic components
– hasNext()
• returns true if the iterator has any more items
– next()
• returns the next item in the iterator
Example
• Print out each item in a vector
Vector v = new Vector();
addItems(v);
Iterator it = v.iterator();
while(it.hasNext())
System.out.println(it.next().toString());
Iterator
hasNext() == true
next
hasNext() == true
next
hasNext() == false
next
Warning
• Note that the next pointer is out-of-bounds
after the last call to next()
– another call to next() will result in exception
• Should always call hasNext() before
calling next()
Implementation
• Three main ways to implement an iterator
– single class for an iterator
• requires all data structures to implement an iterator
specific interface
– create a separate, custom iterator class for
each data structure
– create a custom iterator class for each data
structure and make it an inner class inside the
appropriate data structure
Single Iterator Class
• Implement a single class called Iterator
• Force each data structure that allows
iterators to implement an iterator interface
interface DSIterator {
public int size();
public Object getIndex(int index);
Iterator Class
class Iterator {
private DSIterator ds;
private int nextItem;
public Iterator(DSIterator ds) {
this.ds = ds;
nextItem = 0;
}
public boolean hasNext() {
return nextItem < ds.size();
}
public Object next() {
Object obj = ds.getIndex(nextItem);
nextItem++;
return obj;
}
}
Questions
• What happens if user calls next() at end of
data?
• How many times can user to through
iterator?
• How does user go through the data again?
Notes on Single Iterator Class
• Advantages
– only have to write the iterator class once
• Disadvantage
– performance can suffer greatly for some data
structures
Linked List Example
class LinkedList implements DSIterator {
// start of normal linked list code
...
// end of normal linked list code
private int size; // increment (decrement) in add (delete) methods
public int size() {
return size;
}
public Object getIndex(int index) {
Object tmp = head;
for(int i=0; i<index; i++, tmp = tmp.next);
return tmp;
}
Linked List Example
• Notice the problem with the getIndex()
method
– O(n) performance
• Want our iterator to return the next item in
O(1) time
• Will need a different implementation of the
iterator for a list than for a vector
Custom Class
• Previous example shows the need for
custom iterator classes for different data
structures
• Custom class will:
– take data structure object through constructor
– set a pointer to the first data item
– define next() method that works in O(1) time
Linked List Implementation
class LLIterator {
private Node nextItem;
public LLIterator(LinkedList list) {
nextItem = list.head;
}
public boolean hasNext() {
return nextItem != null;
}
public Object next() {
Object obj = nextItem.data;
nextItem = nextItem.next;
return obj;
}
}
Notes on Custom Iterator Classes
• Advantage
– very good performance
• next() is always O(1)
• Disadvantage
– head of Linked List must be made public
• this is a bad thing – why?
– have to write a custom iterator for each data
type
• means the user must know which one to use for
which data type
Nested Iterator Class
• Java allows one class to be nested inside
another
• Nest class has full access to private data
of main class
– can now let iterator access head
– head is still kept as a private field
Full Example
• Another version of the linked list
interface Iterator {
public boolean hasNext();
public Object next();
}
class LinkedList {
private Node head;
// put all the usual stuff here
public class LLIterator implements Iterator {
private Node nextObject;
public LLIterator() {
nextObject = head;
}
}
public Iterator iterator() {
return new Iterator();
}
}
Notes on Nested Class
• Advantage
– get the same performance as custom class
• it still is a custom class
– encapsulation remains in tact
• head gets to stay private
• Disadvantage
– custom iterator for each data structure
– a bit more confusing to learn and understand
Using Iterators
• Assume a nested iterator class
public void printContents(Object ds) {
Iterator it = ds.iterator();
while(it.hasNext())
System.out.println(it.next().toString());
}
• The above code will work with any data
structure
– of course, it assumes the data structure class
supports iterators
Download