Title: Computer Science 209
1Computer Science 209
- Introduction to Design Patterns
- Iterators
2Patterns and Design Problems
- A design pattern gives advice about solving a
problem in software design - Different problems often have features in common
- A design pattern captures a common way of solving
problems in a set of rules
3Example Visiting a Set of Items in Sequence
StringTokenizer tokens new StringTokenizer("The
cat is on the mat") while (tokens.hasMoreTokens()
) System.out.println(tokens.nextToken())
IteratorltStringgt iter aSet.iterator() while
(iter.hasNext()) System.out.println(iter.next
())
Scanner reader new Scanner(blah blah
blah) while (reader.hasNext()) String data
reader.nextLine() System.out.println(data)
4The Iterator Pattern
- The iterator pattern captures the common elements
of this set of problems and gives advice, in the
form of a set of rules, for solving them - Each pattern has
- a short name
- a brief description of the context
- a lengthy description of the problem
- a prescription for a solution
Proven advice in a standard format
5The Iterator Pattern Context
- An aggregate contains elements
- Clients need to access the elements
- The aggregate should not expose its internal
structure - There may be multiple clients that need
simultaneous access
6The Iterator Pattern Solution
- Define an iterator class that fetches one element
at a time - Each iterator object tracks the position of the
next element - Because there might be multiple aggregate and
iterator classes, it is best to have a single
iterator interface
7The IteratorltEgt Interface
public interface IteratorltEgt public boolean
hasNext() public E next() public void
remove()
remove deletes the object most recently
accessed with next. remove must be included in
the implementing class, but need not be supported
(can throw an UnsupportedOperationException)
8Using an Iterator
// add a bunch of objects to col IteratorltSomeTyp
egt iter col.iterator()
Every aggregate class that supports an iterator
must provide an iterator method. This method
returns an instance of a class that implements
the Iterator interface.
anIterator
anAggregate
A sequence of elements
9Using an Iterator
// add a bunch of objects to col IteratorltSomeTyp
egt iter col.iterator() while
(iter.hasNext()) SomeType obj iter.next()
System.out.println(obj)
collection
D
D
D
iterator
10Using an Iterator
// add a bunch of objects to col IteratorltSomeTyp
egt iter col.iterator() while
(iter.hasNext()) SomeType obj iter.next()
System.out.println(obj)
collection
D
D
D
iterator
11Using an Iterator
// add a bunch of objects to col IteratorltSomeTyp
egt iter col.iterator() while
(iter.hasNext()) SomeType obj iter.next()
System.out.println(obj)
collection
D
D
D
iterator
12Using an Iterator
// add a bunch of objects to col IteratorltSomeTyp
egt iter col.iterator() while
(iter.hasNext()) SomeType obj iter.next()
System.out.println(obj)
collection
D
D
D
iterator
13Preconditions on Methods
public boolean hasNext() public E next()
- hasNext has no preconditions
- next has two preconditions
- hasNext returns true
- the underlying collection has not been modified
by one of - that collections mutators during the lifetime
of that - iterator
14Error Run Out of Elements
// Add a bunch of objects to col IteratorltSomeTyp
egt iter col.iterator() while
(iter.hasNext()) SomeType obj iter.next()
ltblah blah blahgt SomeType obj iter.next()
// This should cause an exception
15Error Inconsistent Data
// Add a bunch of objects to col IteratorltSomeTyp
egt iter col.iterator() while
(iter.hasNext()) col.removeLast()
SomeType obj iter.next() // This should cause
an exception
Using mutators in conjunction with iterators is a
bad practice
16Preconditions
// Throws a NoSuchElementException if hasNext()
is false // Throws a ConcurrentModificationExcept
ion if the // iterators backing store (the
collection) has been modified // by the
collections mutators public E next()
17Preconditions
// Throws an IllegalStateException if next() has
not yet been called // or if remove() has
already been called since the last next() public
void remove()
18An Iterator Implementation
import java.util.Iterator // To see
Iterator public interface TrueStackltEgt
public boolean isEmpty() public IteratorltEgt
iterator() public E peek() public E
pop() public void push(E element) public
int size()
Include an iterator method in the interface.
19An Iterator Implementation
import java.util. // To see Iterator and
exceptions public class ArrayStackltEgt implements
TrueStackltEgt private ListltEgt elements new
ArrayListltEgt() // Code for push, pop, peek,
size, and isEmpty // Code for the iterator
method // Code for the class that implements
the Iterator // interface
Define the iterator class as a private inner
class.
20The Implementing Class
public IteratorltEgt iterator() return new
StackIteratorltEgt() private class
StackIteratorltEgt implements IteratorltEgt
public boolean hasNext() return false
public E next() return null
public void remove()
Nested within ArrayStack
21Tracking Modifications
private int modCount 0 // An ArrayStack
instance variable used to test // for concurrent
modifications
modCount is set to 0 when the collection is
created. modCount is incremented whenever the
collection is modified by one of its
mutators. modCount is compared to the iterators
expected mod count as a precondition for next
22Data Within the Iterator
private class StackIteratorltEgt implements
IteratorltEgt private int curPos,
expectedModCount private StackIterator()
curPos 0 expectedModCount
modCount // Other Iterator methods
Track the iterators current position and its
notion of the mod count
23Implementation of hasNext
private class StackIteratorltEgt implements
IteratorltEgt private int curPos,
expectedModCount public boolean hasNext()
return curPos lt elements.size()
24Implementation of next
private class StackIteratorltEgt implements
IteratorltEgt private int curPos,
expectedModCount public E next() if
(modCount ! expectedModCount) throw new
ConcurrentModificationException(
"Cannot mutate in context of iterator")
if (! hasNext()) throw new
NoSuchElementException( "There
are no more elements") curPos
return elements.get(curPos 1)
25Implementation of remove
private class StackIteratorltEgt implements
IteratorltEgt private int curPos,
expectedModCount public void remove()
throw new UnsupportedOperationException(
"remove not supported by Stack")
Removing objects with an iterator would violate
the spirit of the Stack interface, which
stipulates that items can only be removed from
the top of the collection
26Using an Iterator or
// add a bunch of objects to col IteratorltSomeTyp
egt iter col.iterator() while
(iter.hasNext()) SomeType obj iter.next()
System.out.println(obj)
collection
D
D
D
iterator
27An Enhanced for Loop
// add a bunch of objects to col for (SomeType
obj col) System.out.println(obj)
To get this capability, cols class must
implement the IterableltEgt interface
collection
D
D
D
iterator
28The IterableltEgt Interface
Iterable
import java.util.Iterator public interface
IterableltEgt public IteratorltEgt iterator()
Collection
public interface CollectionltEgt extends
IterableltEgt // omit iterator method here
All collections must implement iterator and can
be used in an enhanced for loop
29The IterableltEgt Interface
Iterable
import java.util.Iterator public interface
IterableltEgt public IteratorltEgt iterator()
TrueStack
public interface TrueStackltEgt extends
IterableltEgt // omit iterator method here
All true stacks must implement iterator and can
be used in an enhanced for loop
30What about a Linked Stack?
- Could use same code for iterator as in ArrayStack
- Problem get runs in linear time!
private class StackIteratorltEgt implements
IteratorltEgt private int curPos,
expectedModCount public E next()
return elements.get(curPos 1)