design pattern #2: iterator · cisc 323, winter 2003, design patterns 1 design pattern #2: iterator...
TRANSCRIPT
CISC 323, Winter 2003, Design Patterns 1
Design Pattern #2: Iterator
There are many kinds of data structures for storing a collection of data.
Common need: take some action with each element of the collection
Example: list of numbers• add up all the numbers• look for a particular number• check to see if any number is outside the legal range• check to see if the collection is in numerical order
Common feature of all these operations: need to walk through collection in order, doing something with each element. Called iterating over a collection.
CISC 323, Winter 2003, Design Patterns 2
Recall CourseList Interface
"first" and "rest" from previous example omitted for simplicity
<<interface>>CourseList
numElements(): intinList(Course c): boolean remove(Course c)add(Course c)get(int n): Course
Course*
CISC 323, Winter 2003, Design Patterns 3
Implementations of CourseList
Many possible implementations including:• array• Vector• linked list• tree (BST, AVL, 2,4 tree, etc.)• hash table
Whichever we choose, details should be invisible to user
Might want to provide multiple implementations with different performance characteristics:• times for each operation (add, remove, get)• space versus time• are Courses kept in some kind of order?
CISC 323, Winter 2003, Design Patterns 4
Iterating Over a CourseList
Why would we need to iterate over a course list?• print a list of all the courses• look for courses that match some criteria
CISC coursesgraduate coursesetc.
• add up total enrollment• create a schedule• allocate rooms for each course• etc.
CISC 323, Winter 2003, Design Patterns 5
How To Iterate
The CourseList interface gives us a get method, which we could use to iterate over the list:
for (int i = 0; i < clist.numElements; i++) {Course c = clist.get(i);... do something with c
}
Problem: Very inefficient for many implementations.
CISC 323, Winter 2003, Design Patterns 6
Linked List Implementation
course 1head course 2 course 3 ....
to get element n:• start at head of list• advance n times• slow if list is long and n is large
so iteration using get method is inefficient
CISC 323, Winter 2003, Design Patterns 7
Better Way For Linked Lists
for (LinkedNode node = head; node != null; node = ptr.next) {...do something with node.course...
}
course 1head course 2 course 3 ....
Problem: user needs access to internal data
CISC 323, Winter 2003, Design Patterns 8
General Question
How can we provide an efficient, convenient way for the user to iterate over a collection while still hiding implementation details?• user doesn't have to take the time to learn about data
structure being used• don't give user permission to mess with internal data
Answer: create a separate object to control iteration
Called an Iterator
Another advantage: write logic for iterating once only, not for each loop.
CISC 323, Winter 2003, Design Patterns 9
Common Elements of Iteration
What does an Iterator object have to do?1. begin an iteration (i.e. start with the first element)2. tell user if we're finished (i.e. are there more elements?)3. get the current element4. advance to the next element
CISC 323, Winter 2003, Design Patterns 10
Iterating Over a Linked List
for (LinkedNode node = head; node != null; node = ptr.next) {...do something with node.course...
}
begin the iteration
CISC 323, Winter 2003, Design Patterns 11
Iterating Over a Linked List
for (LinkedNode node = head; node != null; node = ptr.next) {...do something with node.course...
}
are we done yet?
CISC 323, Winter 2003, Design Patterns 12
Iterating Over a Linked List
for (LinkedNode node = head; node != null; node = ptr.next) {...do something with node.course...
} access the current element
CISC 323, Winter 2003, Design Patterns 13
Iterating Over a Linked List
for (LinkedNode node = head; node != null; node = ptr.next) {...do something with node.course...
}
advance to next element
CISC 323, Winter 2003, Design Patterns 14
Iterating Over an Array
for (int i = 0; i < size; i++) {...do something with courses[i]...
}
begin the iteration
CISC 323, Winter 2003, Design Patterns 15
Iterating Over an Array
for (int i = 0; i < size; i++) {...do something with courses[i]...
}
are we done yet?
CISC 323, Winter 2003, Design Patterns 16
Iterating Over an Array
for (int i = 0; i < size; i++) {...do something with courses[i]...
} access the current element
CISC 323, Winter 2003, Design Patterns 17
Iterating Over an Array
for (int i = 0; i < size; i++) {...do something with courses[i]...
}
advance to next element
CISC 323, Winter 2003, Design Patterns 18
A CourseList Iterator<<interface>>CourseList
numElements(): intinList(Course c): boolean remove(Course c)add(Course c)get(int n): CoursecreateIterator(): CourseListIterator
Course*
<<interface>>CourseListIterator
first(): Coursenext(): CourseIsDone(): booleanCurrentItem(): Course
createsiterates over
Think of an iterator as an object that "points to" an element in the list.
CISC 323, Winter 2003, Design Patterns 19
Using an IteratorCourseList myList = ....;....CourseListIterator iter = myList.createIterator();while (!iter.IsDone()) {
Course thisCourse = iter.currentItem();... do something with thisCourse ...iter.next(); // move to next item
} // end while
// to start a new iteration:iter.first(); // resets to the beginning of the list
CISC 323, Winter 2003, Design Patterns 20
Java Class: Enumeration
Previous example used Design Patterns terminology for Iterator methods.Java API includes Enumeration interface (in java.util)• provides the same functionality• different method names
When writing in Java, nice to use Enumeration since it's familiar to Java programmers.
public interface Enumeration {public boolean hasMoreElements();public Object nextElement();
}
CISC 323, Winter 2003, Design Patterns 21
Enumeration Methodspublic boolean hasMoreElements():
• returns true if there are more elements to look at• exactly like !isDone()public Object nextElement();
• returns current element and advances to next• combines currentItem and next• so:
Course thisCourse = (Course)enum.nextElement();
• is equivalent to:Course thisCourse = iter.currentItem();iter.next(); // move to next item
There is no method to start the enumeration over at the beginning like first(). To do that, create a new enumeration.
CISC 323, Winter 2003, Design Patterns 22
Implementing Enumeration for Course Lists
We will need an implementation of Enumeration for each implementation of CourseList
CISC 323, Winter 2003, Design Patterns 23
Using Inner Classes
The Enumeration needs access to the internal data structures of the course listWe don't want to give all user's such accessSolution: implement Enumerations as inner classes• ArrayEnum is inner class of CourseArrayList• LinkedEnum is inner class of CourseLinkedList
User doesn't have to keep track of these inner classesUser calls enumeration() method and is given the appropriate kind of Enumeration objectExample of a "factory method": a method that creates an object and takes care of deciding what particular kind of object
CISC 323, Winter 2003, Design Patterns 24
Linked List Implementation (1)public class CourseLinkedList implements CourseList {private class ListNode {Course course;ListNode next;
}private ListNode head = null;
// get, remove, etc.
CISC 323, Winter 2003, Design Patterns 25
Linked List Implementation (2)public class CourseLinkedList implements CourseList {private class ListNode {Course course;ListNode next;
}private ListNode head = null;
// get, remove, etc.
private class LinkedEnum implements Enumeration {...
} // end inner class LinkedEnum
CISC 323, Winter 2003, Design Patterns 26
Linked List Implementation (3)public class CourseLinkedList implements CourseList {private class ListNode {Course course;ListNode next;
}private ListNode head = null;
// get, remove, etc.
private class LinkedEnum implements Enumeration {...
} // end inner class LinkedEnum
public Enumeration enumeration() { return new LinkedEnum();
} // end enumeration
} // end class CourseLinkedList
CISC 323, Winter 2003, Design Patterns 27
Details of Inner Classprivate class LinkedEnum implements Enumeration {ListNode nextNode = head; // next element to return
public boolean hasMoreElements() {return nextNode != null;
}
// Java convention: throw an exception if you've already// gone through all the elementspublic Object nextElement() throws NoSuchElementException {if (!hasMoreElements()) {throw new NoSuchElementException();
}else {Course returnVal = nextNode.course;nextNode = nextNode.next;return returnVal;
} // end if} // end nextElement
} // end inner class LinkedEnum
CISC 323, Winter 2003, Design Patterns 28
Array Implementation
Contains inner class: ArrayEnumInstead of node pointer, inner class contains index of next elementfull code for example is on the web page (link near the slides)
CISC 323, Winter 2003, Design Patterns 29
Using a CourseList EnumerationCourseList myList = new CourseArrayList();... add elements to myList
// a loop to print all courses in listEnumeration listEnum = myList.enumeration();while (listEnum.hasMoreElements()) {
Course c = (Course) listEnum.nextElement();System.out.print(c + " ");
} // end whileSystem.out.println();
To use the linked list implementation instead:CourseList myList = new CourseLinkedList();
No other changes necessary.Iterating over the list is independent of implementation.
CISC 323, Winter 2003, Design Patterns 30
General Iterator Design Pattern
CISC 323, Winter 2003, Design Patterns 31
Danger: Changing the Collection
What happens if you change the underlying collection during an iteration?Example:CourseList myList = new CourseArrayList();myList.add(new Course("CISC 121"));myList.add(new Course("ELEC 276"));myList.add(new Course("CISC 323"));Enumeration enum = myList.enumeration();Course course1 = (Course) enum.nextElement();Course course2 = (Course) enum.nextElement();myList.remove(course1);Course course3 = (Course) enum.nextElement();
Throws an exception. The enumeration was storing an index into the array of courses. When we removed an earlier course, the index became invalid.
CISC 323, Winter 2003, Design Patterns 32
Robust Iterators
A "robust iterator" is an iterator that doesn't fail even if you add to or remove from the underlying collection.Robust iterators are hard to writeMost iterators are not robust
CISC 323, Winter 2003, Design Patterns 33
The Java Iterator Class
The Enumeration class came with Java 1.0Version 1.2 & later include a new class: Iteratorrenames the two methods from Enumerationcontains an additional method for removing an element from the underlying collection: allows filtering a collection
Reasons we've taught you Enumeration class instead:• still used and included in Java API• remove method is not part of Iterator design pattern• code you will use for Assignment 3 includes Enumerations