200 likes | 312 Views
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.
E N D
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