Title: Comp 401 Iterator Design pattern
1Comp 401Iterator Design pattern
2Object-based Scanning
- Redo the scanning solution
- Monolithic, single class solution
- does UI and scanning
- No reuse of code
- Another scanning problem to show reuse
- Illustrate streams and iterator design pattern
3Upper case printing
4Upper case printing
package warmup public class AnUpperCasePrinter
public static void main(String
args) // assume user enters arguments
correctly System.out.println("Upper Case
Letters") int index 0 while (index lt
args0.length()) if (Character.isUpperCase(ar
gs0.charAt(index))) System.out.print(args0
.charAt(index)) index System.out.println
()
5Printing Scanned Characters Forwards and Backwards
Solution cannot scan multiple times
6Solution
package warmup public class AReverseUpperCasePrin
ter static final int MAX_CHARS 5 static
char upperCaseLetters new charMAX_CHARS st
atic int numberOfUpperCaseLetters 0 public
static void main(String args) int index
0 System.out.println("Upper Case
Letters") while (index lt args0.length())
if (isUpperCase(args0.charAt(index)))
System.out.print(args0.charAt(index))
storeChar(args0.charAt(index)) index
System.out.println() printReverse()
7Solution (contd.)
public static void storeChar(char c) if
(numberOfUpperCaseLetters MAX_CHARS)
System.out.println("Too many upper case
letters. Terminating program. ") System.exit(-
1) upperCaseLettersnumberOfUpperCaseLetter
s c numberOfUpperCaseLetters public
static void printReverse() System.out.printl
n("Upper Case Letters in Reverse") for (int
index numberOfUpperCaseLetters - 1 index gt 0
index--) System.out.print(upperCaseLettersin
dex) System.out.println()
8Two Scanning Problems
One UI is a subset of the other
What about the code?
9No reuse in Monolithic Solutions
int index 0 System.out.println("Upper Case
Letters ")//token processing while (index lt
args0.length()) if (Character.isUpperC
ase(args0.charAt(index)))
System.out.print(args0.charAt(index)) // token
processing index
int index 0 System.out.println("Upper Case
Letters ")//token processing while (index lt
args0.length()) if (Character.isUpperC
ase(args0.charAt(index)))
System.out.print(args0.charAt(index)) //
token processing storeChar(args0.charAt(index
)) index
Only difference
How to put it in separate class that only scans
and does not store?
10Division of Labor in Character Scanning
Scanner class that produces tokens
Main class that processes tokens (prints and/or
stores tokens)
11Index-Based Interface?
AnIndexedBasedScanner
Main class that processes tokens (prints and/or
stores tokens)
12Index-based Interface
public interface IndexBasedScanner public
String getTokenArray () public int
getNumberOfTokens ()
13Implementation with Array Property
public class AnIndexBasedScanner implements
IndexBasedScanner static final int MAX_CHARS
5 String upperCaseLetters int
numberOfUpperCaseLetters public
AnIndexBasedScanner(String theScannedString)
scan(theScannerString) void scan (String
theScannedString) // store all scanned
tokens in upperCaseLetters public
String getTokenArray () return
upperCaseLetters public int
getNumberOfTokens return numberOfUpperCaseLett
ers
All tokens scanned even if only some may be used
by code processing the tokens.
14Better Scanning Interface?
Scanner class that produces tokens
Analogy with Division of Labor in Radio Station
Scanning
Main class that processes tokens (prints and/or
stores tokens)
15Division of Labor in Radio Scanning
16Division of Labor in Radio Scanning
17Division of Labor in Radio Scanning
18Division of Labor in Radio Scanning
19Division of Labor in Radio Scanning
20Division of Labor in Radio Scanning
21Division of Labor in Radio Scanning
22Division of Labor in Radio Scanning
?
23Division of Labor in Radio Scanning
24Analogous Division of Labor
Scanner class that produces tokens
Main class that processes tokens (prints and/or
stores tokens)
25Division of Labor in Character Scanning
Scanner class that produces tokens
Scanner object
Instance of
Intantiates
Uses Invokes methods in
Main class that processes tokens (prints and/or
stores tokens)
Java input libraries illustrate this division of
labor in scanning
26Using Java Scanning Libraries
BufferedReader dataIn new BufferedReader (new
InputStreamReader( System.in)) int product
1 // add input list terminated by a negative
number while (true) int num Integer.parseInt
(dataIn.readLine()) if (num lt 0) break
product productnum System.out.println
(product)
Parameter to InputStreamReader
Parameter to BufferedReader
Give next line in sequence of input lines
27Constructor parameters
- InputStreamReader takes System.in as parameter.
- BufferedReader takes InputStreamReader as
parameter. - In general, scanner takes object producing
scanned stream as parameter.
28Division of Labor in I/O
BufferedReader Class
BufferedReader Object
Instance of
Intantiates
Uses Invokes methods in
Main class that does I/O
29BufferedReader Operations
Multi-line input stream
Line stream
Line 1
Line 2
dataIn.readLine()
Line 1
dataIn.readLine()
Line 2
dataIn.readLine()
IOException
30Scanner Interface?
Input stream
Token Stream
token 1
token 2
scanner.next ()
token 1
scanner.next ()
token 2
scanner.next ()
ScannerException
31Scanner Interface?
Input stream
Token Stream
token 1
token 2
scanner.next ()
token 1
scanner.next ()
token 2
scanner.hasNext()
false
scanner.next ()
???
32Uppercase Scanner Interface?
token 1
token 2
token 3
scanner.next ()
J
scanner.next ()
F
scanner.next()
K
Can check hasNext() before calling next().
scanner.hasNext()
false
scanner.next ()
???
33Multiple Iterator Interfaces
package iterators public interface CharIterator
public char next () public boolean
hasNext()
package iterators public interface
StringIterator public String next ()
public boolean hasNext()
package ltPgt public interface ltTypegtIterator
public ltTypegt next () public boolean
hasNext()
34Using an Iterator Interface
public static void printChars (CharIterator
charIterator) while (charIterator.hasNex
t()) System.out.print(charIterator.n
ext ())
Normally need to check hasNext() before each call
to next()!
Unless expecting a certain minimum number of
tokens (e.g. move 50)
35Redoing UpperCasePrinter
package main import iterators.CharIterator impor
t iterators.AnUpperCaseIterator public class
UpperCasePrinter public static void main
(String args) printUpperCase(args0)
public static void printUpperCase(String s)
System.out.println("Upper Case
Letters") printChars (new
AnUpperCaseIterator(s)) public
static void printChars (CharIterator
charIterator) while (charIterator.hasNex
t()) System.out.print(charIterator.ne
xt ())
36Implementing Scanner
package iterators public class
AnUpperCaseIterator implements CharIterator
public AnUpperCaseIterator(String
theString) ...
public boolean hasNext() ...
public char next () ...
37Simple Storage-based Approach No Scanning in
next(), hasNext()
public class AnUpperCaseIterator implements
CharIterator static final int MAX_CHARS
5 String upperCaseLetters int
numberOfUpperCaseLetters . public
AnUpperCaseIterator(String theString)
scanAndStore(theString) void
scanAndStore (String theString) // store all
scanned tokens in array public boolean
hasNext() . public String next()
Not property
Non trivial
Again, all tokens scanned even if only some may
be used by code processing the tokens.
38Simple Storage-based Approach No Scanning in
next(), hasNext()
- Perform all the scanning in a single method, as
before. - While scanning, store each token in some list
such as array. - Call this method from the constructor.
- next() accesses the array.
- All scanning occurs before first call to next().
- Less time efficient Must scan all elements even
if user of scanner only wants first few tokens. - Less space efficient List takes space.
- Less modular All scanning in one method.
39Indexing vs. Iteration
- In both cases elements from an ordered sequence
are accessed. - Indexing allows random access, access to elements
in any order. - Which to use when (some) elements are accessed in
order?
- Indexing less efficient random access requires
storing all sequence elements in memory, which
takes time and space. - Indexing (slightly) more difficult to use Object
user must keep track of next element index.
Iterator can but does not need to store
40Three Approaches to Reusable Scanner
- Indexing interface
- Requires storing all tokens.
- Iterator interface
- Store all tokens.
- Do not store all tokens, each call to next()
scans next token.
41Indexing Interface
public class AnIndexBasedScanner implements
IndexBasedScanner static final int MAX_CHARS
5 String upperCaseLetters int
numberOfUpperCaseLetters public
AnIndexBasedScanner(String theScannedString)
scan(theScannerString) void scan (String
theScannedString) // store all scanned
tokens in upperCaseLetters public
String getTokenArray () return
upperCaseLetters public int
getNumberOfTokens return numberOfUpperCaseLett
ers
All tokens scanned even if only some may be used
by code processing the tokens.
42Storing Iterator
public class AnUpperCaseIterator implements
CharIterator static final int MAX_CHARS
5 String upperCaseLetters int
numberOfUpperCaseLetters . public
AnUpperCaseIterator(String theString)
scanAndStore(theString) void
scanAndStore (String theString) // store all
scanned tokens in array public boolean
hasNext() . public String next()
Not property
Non trivial
Again, all tokens scanned even if only some may
be used by code processing the tokens.
43Iterator that does not store
package iterators public class
AnUpperCaseIterator implements CharIterator
public AnUpperCaseIterator(String
theString) ...
public boolean hasNext() ...
public char next () ...
44Data Structure Scanned String
package iterators public class
AnUpperCaseIterator implements CharIterator
String string public
AnUpperCaseIterator(String theString)
string theString ...
public boolean hasNext() ...
public char next () ...
45Data Structure Marker
string
J
o
h
n
F
.
K
e
n
n
d
y
e
Scanned part
Unscanned part
nextElementPos
nextElementPos is a global rather than loop
variable
Changed when next() is called
Accessed when hasNext() is called
All methods (next(), hasNext(), and internal
methods called by them written for different
kinds of tokens) must agree on where it points at
various points in scanning process.
46next ()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
public char next ()
47next ()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
//Assume nextElemPos is at start of next token or
end of string when //method is called. //Method
makes sure this is also true before
returning. //returns next element if one
exists public char next()
48next ()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
//Assume nextElemPos is at start of next token or
end of string when //method is called. //Method
makes sure this is also true before
returning. //returns next element if one
exists public char next()
while (!isUpperCase(string.charAt(nextElementPos))
)
nextElemPos
49next ()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
//Assume nextElemPos is at start of next token or
end of string when //method is called. //Method
makes sure this is also true before
returning. //returns next element if one
exists public char next()
movePastCurrentToken()
skipNonTokenCharacters()
50next ()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
//Assume nextElemPos is at start of next token or
end of string when //method is called.
//returns next token if one exists public char
extractToken()
return string.charAt(nextElementPos)
51movePastCurrentToken()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
//Assume nextElemPos is at start of next token or
end of string when //method is called. //Moves
past current token. public void
movePastCurrentToken()
nextElemPos
52skipNonTokenCharacters()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
// keep advancing nextElementPos until we hit the
next upper case public void skipNonTokenCharact
ers()
while (! isUpperCase(string.charAt(nextElementPos)
))
nextElemPos
53skipNonTokenCharacters()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
// keep advancing nextElementPos until we hit the
next upper case or go // beyond the end of the
string. public void skipNonTokenCharacters()
while (nextElementPos lt string.length()
!Character.isUpperCase(string.charAt(nextElementP
os)))
nextElemPos
54Initialization
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
String string int nextElementPos 0 public
AnUpperCaseIteratorString theString)
string theString
55Initialization
string
j
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
String string int nextElementPos 0 public
AnUpperCaseIteratorString theString)
string theString
skipNonTokenCharacters()
56hasNext()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
public boolean hasNext () ...
57hasNext()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
public boolean hasNext () ...
58hasNext()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
public boolean hasNext () ...
59hasNext()
string
J
o
h
n
F
.
K
e
n
n
d
y
e
nextElementPos
//return false if nextElementPos is beyond end of
string true otherwise public boolean hasNext ()
return nextElementPos lt string.length()
60Complete Scanner
package iterators public class
AnUpperCaseIterator implements CharIterator
String string int nextElementPos 0
public AnUpperCaseIterator(String theString)
string theString
skipNonTokenCharacters() public
boolean hasNext() return nextElementPos lt
string.length() public char next ()
char retVal extractToken()
movePastCurrentToken()
skipNonTokenCharacters() return retVal
void movePastCurrentToken()
nextElementPos void skipNonTokenCharacte
rs() while (nextElementPos lt
string.length() !Character.isUpperCase(string.
charAt(nextElementPos)))
nextElementPos char
extractToken() return string.charAt(nextElementP
os)
61Scanner Pattern
package ltPgt public class ltScanner Namegt
implements ltTgtIterator String string
int nextElementStart 0 int nextElementEnd
// may not be global variable public ltScanner
Namegt (String theString) string
theString skipNonTokenCharacters()
public boolean hasNext() return
nextElementStart lt string.length() public
ltTgt next () ltTgt retVal
extractToken() movePastCurrentToken(getLe
ngth(retVal)) skipNonTokenCharacters()
return retVal void
movePastCurrentToken() void
skipNonTokenCharacters() ltTgt
extractToken()
62Multiple Token Types
package ltPgt public class ltScanner Namegt
implements ltTgtIterator String string
int nextElementStart 0 int nextElementEnd
// may not be global variable public ltScanner
Namegt (String theString) string
theString skipNonTokenCharacters()
public boolean hasNext() return
nextElementStart lt string.length() public
ltTgt next () ltTgt retVal
extractToken() movePastCurrentToken(getLe
ngth(retVal)) skipNonTokenCharacters()
return retVal void
movePastCurrentToken() void
skipNonTokenCharacters() ltTgt
extractToken()
Need multiple next(), extractToken(), ..
e.g. nextNumber(), extractNumber
e.g. nextWord(), extractWord
next() calls appropriate nextTokenType() method
based on first token character.
e.g. if isDigit(firstTokenChar), return
nextNumber(), else if isLetter(firstTokenChar)
return nextWord()
63Division of Labor in Character Scanning
Scanner class that produces tokens
Scanner object
Instance of
Intantiates
Uses Invokes methods in
Main Class that processes( prints and/or stores
tokens)
64Forward Printing
AnUpperCaseIterator
AnUpperCaseIterator instance
Instance of
Intantiates
Uses Invokes methods in
AnUpperCasePrinter
65Forward and Reverse Printing
AnUpperCaseIterator
AnUpperCaseIterator instance
Instance of
Intantiates
Uses Invokes methods in
AReverseUpperCasePrinter
66UpperCasePrinter
package main import iterators.CharIterator impor
t iterators. AnUpperCaseIterator public class
UpperCasePrinter public static void main
(String args) printUpperCase(args0)
public static void printUpperCase(String s)
System.out.println("Upper Case
Letters") printChars (new
AnUpperCaseIterator(s)) public
static void printChars (CharIterator
charIterator) while (charIterator.hasNex
t()) System.out.print(charIterator.ne
xt ())
67Forward and reverse printing
package main import iterators.CharIterator impor
t iterators.AnUpperCaseIterator public class
AReverseUpperCasePrinter static final int
MAX_CHARS 5 static char upperCaseLetters
new charMAX_CHARS static int
numberOfUpperCaseLetters 0 public static
void main(String args) printAndStore(args0)
printReverse()
68Forward and reverse printing
public static void printAndStore (String s)
System.out.println("Upper Case
Letters") printAndStore (new
AnUpperCaseIterator(s)) public
static void printAndStore (CharIterator
charIterator) while (charIterator.hasNex
t()) char inputChar
charIterator.next ()
System.out.print (inputChar)
storeChar(inputChar)
System.out.println()
69Forward and reverse printing (contd.)
public static void storeChar(char c) if
(numberOfUpperCaseLetters MAX_CHARS)
System.out.println("Too many upper case
letters. Terminating program. ") System.exit(-
1) upperCaseLettersnumberOfUpperCaseLetter
s c numberOfUpperCaseLetters public
static void printReverse() System.out.printl
n("Upper Case Letters in Reverse") for (int
index numberOfUpperCaseLetters - 1 index gt 0
index--) System.out.print(upperCaseLettersin
dex)
70Reuse of Iterator
Scanner use in AReverseUpperCasePrinter
while (charIterator.hasNext()) char nextChar
charIterator.next()) System.out.print(nextChar)
storeChar(nextChar)
Scanner use in AnUpperCasePrinter
while (charIterator.hasNext())
System.out.print(charIterator.next ())
71No reuse in Monolithic Solutions
int index 0 System.out.println("Upper Case
Letters ")//token processing while (index lt
args0.length()) if (Character.isUpperC
ase(args0.charAt(index)))
System.out.print(args0.charAt(index)) // token
processing index
int index 0 System.out.println("Upper Case
Letters ")//token processing while (index lt
args0.length()) if (Character.isUpperC
ase(args0.charAt(index)))
System.out.print(args0.charAt(index)) //
token processing storeChar(args0.charAt(index
)) index
Only difference
How to put it in separate class that only scans
and does not store?
72Need Reuse?
package warmup public class AnUpperCasePrinter
public static void main(String
args) // assume user enters arguments
correctly System.out.println("Upper Case
Letters") int index 0 while (index lt
args0.length()) if (Character.isUpperCase(ar
gs0.charAt(index))) System.out.print(args0
.charAt(index)) index System.out.println
()
initialize while there is more input set next
line application-specific code to process
next line move next line markers
Input scanning code would be much more complex
73Iterator vs. Scanning
public interface CharIterator public char
next () public boolean hasNext()
74Iterator without Scanning
A
B
...
Z
AllUppercaseLettersInOrder
implements
public interface CharIterator public char
next () public boolean hasNext()
75Iterating all Uppercase Letters
//instance variables ???
public char next () ???
public boolean hasNext() ????
76Iterating all Uppercase Letters
package iterator public class AllUpperCaseLetters
InOrder implements CharIterator char
nextLetter 'A' public boolean hasNext()
return nextLetter lt 'Z'
public char next () char retVal
nextLetter nextLetter (char)
(nextLetter 1) return retVal
77Comparing Two Implementations
J
F
K
AnUpperCaseIterator
implements
public interface CharIterator public char
next() public boolean hasNext()
78Radically Different Behavior
A
B
...
Z
AllUppercaseLettersInOrder
implements
public interface CharIterator public char
next () public boolean hasNext()
Syntactic Specification!
79Can Write Code Reusing Polymorphic Code
A
B
...
Z
AllUppercaseLettersInOrder
implements
public interface CharIterator public char
next () public boolean hasNext()
Syntactic Specification!
80Names Do Not Matter
package iterators public interface CharIterator
public char next () public boolean
hasNext()
Convention used by java.util.Iterator
package enums public interface CharEnumeration
public char nextElement () public boolean
hasMoreElements())
Convention used by java.util.Enumeration
Enumeration vs. enum is confusing
81Definition of Iterator
- Iterator provides
- A method that gives the next object is some
object sequence. - A method or exception or special next object
value that indicates there are no more objects in
the sequence.
Iterator
Iterator User
An application often contains an iterator and its
user.
Iterator is a design pattern.
82Design Pattern
- Inspired by Architectural Pattern
- Reusable programming pattern
- Not specific class or interface, infinite family
of classes/interfaces implement this pattern. - Examples
- Iterator, composite, observer, factory, facade
- Language-independent pattern language
- Usually involves multiple objects
- Iterator and iterator user
83(No Transcript)
84Architectural Pattern
- Christopher 79
- Each pattern is a three part rule, which
expresses a relation between a certain context, a
problem, and a solution. - Each pattern describes a problem which occurs
over and over again in our environment, and then
describes the core of a solution to that problem,
in such a way that you can use this solution a
million times over
85Scanning, Iterator, Streams
- Scanner can be an iterator
- Iterator may not be a scanner
- A stream is another term for an iterator
- InputStreamReader
- BufferedReader
- Console
- ..
- Previous Java stream objects did not implement an
interface. - Java 1.6 provides interface java.io.Console and
object System.console that implements this
interface and automatically composes Sytem.in and
BufferedReader.
86Extra Slides
87(No Transcript)