Title: Chapter 21: Iterators
1Chapter 21 Iterators
2Objectives
- After studying this chapter you should understand
the following - the role of iterators in container classes
- various implementations of the Iterator
interface - iterators as an abstraction of indexes in list
operations - the notion of an internal iterator
- the basic structure of the java.util.Collection
hierarchy.
3Objectives
- Also, you should be able to
- use iterators in algorithms dealing with lists
- define a class that provides a new implement of
the Iterator interface.
4Cost of accessing list elements
- Need to access each element of a list.
- Use index to access an element of the list.
- for array-based implementations get(i) is
constant. - for linked implementations get(i) is linear.
5Cost of accessing list elements
- For a linked implementation
for (int i 0 i lt list.size() i i1) do
something with list.get(i)
int i list.indexOf(element) list.remove(i)
- both statements are linear
- Need Reduce cost of linked-list traversals.
6Iterator
- An object associated with container that
sequentially accesses each element in the
container. - nhUtilites.containers2 contains classes
described. - The standard package java.util includes a
different interface also named IteratorltEgt.
7Iterator
- public interface IteratorltElementgt extends
Cloneable - Iterator for accessing and traversing elements of
a container. - public void reset ()
- Initialize this Iterator to reference the first
element. - public void advance ()
- Advance this Iterator to the next element.
- require !this.done()
- public boolean done ()
- No more elements to traverse in the container.
- public Element get ()
- Element this Iterator currently references.
- require !this.done()
8Iterator (cont)
- public boolean equals (Object obj)
- The specified Object is an Iterator of the same
class as this, and references the same relative
element of the same container. - public boolean traverses (Object container)
- This Iterator traverses the specified container.
- public Object clone ()
- A copy of this Iterator.
- public void setEqualTo (IteratorltElementgt other)
- Set this Iterator to reference the same
container element as the specified Iterator. Both
Iterators must traverse the same container. - require this.traverses(container)
implies other.traverses(container) - ensure this.equals(other)
9Using Iterator
- Assume container c, and i an iterator for it.
- Can access each element in container as follows
i.reset() while (!i.done()) do something with
i.get() i.advance()
- Example To see if element is in container
i.reset() while (!i.done() !i.get().equals(ele
ment)) i.advance()
10int indices and iterators
- An index int variable is a simple for of
iterator - It is reset by setting variable to 0.
- Advanced by incrementing variable .
- It is done when variable equals the length of the
list.
11Iterator implementations
- Every iterator implementation is coupled to its
container.
12Iterator for array-based implementations
- public class ListIteratorltElementgt implements
IteratorltElementgt - private int current // index into
theList - private ListltElementgt theList // the
List this Iterator references - /
- Create a new iterator for the specified List.
- /
- public ListIterator (ListltElementgt list)
- theList list
- current 0
-
13Iterator for array-based implementations
- //Initialize this Iterator to reference the
first - public void reset ()
- current 0
-
- //Advance this Iterator to next element.
- public void advance ()
- current current 1
-
- //No more elements to traverse in the
container. - public boolean done ()
- return current gt theList.size()
-
- //Container element this Iterator currently
references. - public Element get ()
- return theList.get(current)
-
14Iterator for Linked lists
- Define an iterator for LinkedListltElementgt as a
private inner class. - It can then directly access implementation
structure of the LinkedList and of component
Nodes. - It keeps a reference to Node containing current
element.
15Iterator for Linked lists
private class Iterator implements
nhUtilities.containers.IteratorltElementgt
private Node current //Create a new
Iterator for this LinkedList public Iterator ()
reset() //Initialize this Iterator to
reference the first element. public void reset
() current LinkedList.this.first //Adva
nce this Iterator to next element. public void
advance () current current.next
16Iterator for Linked lists
//No more elements to traverse in the
container. public boolean done () return
current null //Container element this
Iterator currently references. public Element get
() return current.element
17Creating iterators for containers
- ListltElementgt includes method for creating an
iterator
public IteratorltElementgt iterator () Create a
new Iterator for this List.
18Default creation of iterators
- AbstractListltElementgt creates ListIteratorltElement
gt as the default iterator.
public abstract class AbstractListltElementgt
implements ListltElementgt public
IteratorltElementgt iterator () return new
ListIteratorltElementgt(this)
- This default implementation is only good for
array-based implementations.
19Creation of LinkedListltElementgt iterators
- The class LinkedListltElementgt,
- overrides iterator() method and returns an
instance of LinkedListltElementgt.Iterator
20ListltElementgt with Iterator parameters
- Wed like to be able to delete the element
identified by an iterator, change it, insert an
element in front of it, etc. - Overload ListltElementgt methods that take index
arguments with methods taking iterator arguments.
21ListltElementgt with Iterator parameters
- public Element get (IteratorltElementgt iterator)
- The Element referenced by the specified Iterator.
- public IteratorltElementgt iteratorAt (Element
element) - An Iterator referencing first occurrence of
specified Element in this ListltElementgt
IteratorltElementgt is done if not found. - public void add (IteratorltElementgt iterator,
Element elm) - Insert Element at position. The Iterator will
reference the newly added Element. - public void remove (IteratorltElementgt iterator)
- Remove Element at position. Iterator will
reference Element following removed Element. If
no Element follows removed Element
iterator.done() is true. - public void set (IteratorltElementgt iterator,
Element elm) - Replace the element at the specified position
with the specified Element.
22Improving Iterator for LinkLists
- LinkedListltElementgt.Iterator references current
node of a LinkedListltElementgt. - Sufficient to implement get and set.
- To implement remove and add, need reference to
Node preceding current Node. - Must traverse list to find needed Node.
23Improving Iterator for LinkLists
- To solve problem
- keep a pair of references in the iterator, one to
the current Node and one to the preceding Node. - Or keep a reference to the Node preceding current
one. - In either case, it will simplify things if
LinkedListltElementgt has a header
24DoublyLinkedListltElementgt Iterators
- It is possible to move forward or backward
through a doubly linked list as each node
contains forward and backward references. - Define an IteratorltElementgt extension that
permits forward and backward traversal of a list,
and ensure that a DoublyLinkedListltElementgt
creates such an iterator.
25BiDirectionalIteratorltElementgt
public interface BiDirectionalIteratorltElementgt
extends IteratorltElementgt public boolean done
() This Iterator has been advanced past the last
element, backed uppast the first element, or the
container is empty. Equivalent to offRight()
offLeft(). public boolean offRight () This
Iterator has been advanced past the last element,
or the container is empty. public boolean
offLeft () This Iterator has been backed up past
the first element, or the container is
empty. public void advance () Move this
Iterator forward to the next element. If
this.offLeft() and the container is not empty,
move to the first element. public void backup
() Move this Iterator back to the previous
element. If this.offRight() and the container is
not empty, move to the last element. require
!this.offLeft()
26Iterators and List modifications
- what will the state of the i iterator be after
executing
list.remove(j) or list.remove(2)
27Iterators and List modifications
- If a List is modified via an index, all Iterators
that reference the List become invalid. - Furthermore, if a List is modified by an
Iterator, all other Iterators that reference the
List become invalid.
28Internal Iterators forEachDo
- Client provides an operation and iterator itself
applies operation to each container element. - They support performing some specific operation
on each item in the container. - We consider adding this feature to the List
interface. - The operation to be performed should be provided
as a method argument, encapsulated in an object.
29Internal Iterators forEachDo
- We define an interface to model an operation
public void execute (Element element) The
operation. public interface OperationltElementgt An
operation to be performed on an Element.
- Method forEachDo has an Operation parameter
// Perform Operation on each element public void
forEachDo (OperationltElementgt operation)
30Internal Iterators forEachDo
- Using an Iterator, forEachDo can be implemented
in AbstractListltElementgt
public void forEachDo (OperationltElementgt
operation) IteratorltElementgt iterator
this.iterator() iterator.reset() while
(!iterator.done()) operator.execute(iterator.g
et()) iterator.advance()
31Internal Iterators forEachDo
- For example, suppose roll is a ListltStudentgt and
want to add ten points to each Students grade
roll.forEachDo( new OperationltStudentgt ()
public void execute(Student element)
element.setGrade(element.getGrade()
10) )
32Limitations of forEachDo
- forEachDo allow to perform an operation on each
list element. - It does not allow to replace elements. Nor to
query list for a value that requires querying
each element. - Handling such problems requires more structure.
33Complexity of List features
feature Array-based linked
get(int) constant Linear
get(Iterator) constant constant
indexOf(Element) linear linear
iteratorAt(Element) linear linear
add(Element) constant constant
add(Iterator,Element) linear constant
add(int, Element) linear linear
remove(int) linear linear
remove(Iterator) linear constant
set(int,Element) constant linear
set(Iterator, Element) constant constant
34The java.util CollectionltElementgt hierarchy
- Java package java.util defines a set of
interfaces and classes rooted at interface
CollectionltElementgt. - This hierarchy contains members closely related
to classes and interfaces described in this
chapter. - The library available since Java 1.2, and
retrofitted for type parameters in Java 1.5.
35The java.util CollectionltElementgt hierarchy
- Collection models a generalized container.
- Some Collections allow duplicate elements, others
do not. - Some Collections impose an ordering on the
elements some are unordered.
36The java.util CollectionltElementgt hierarchy
- Collection methods include
public boolean contains (Element e) This
collection contains the specified element. pubic
boolean isEmpty() This collection contains no
elements. public int size () The number of
elements in this collection. public
java.util.Iterator iterator() An iterator over
the elements in this collection.
37The java.util CollectionltElementgt hierarchy
- Operations add and remove elements are
optional. An implementing class can choose
to support them or not.
public boolean add (Element element)
throws UnsupportedOperationException, ClassCastE
xception, IllegalArgumentException
38The java.util CollectionltElementgt hierarchy
- List extends Collection. This interface models a
sequential collection in which elements can be
accessed by index. - A List can contain duplicate elements, but
operations to add and remove elements are still
specified as optional. - java.util.Set extends Collection and specifies a
Collection that does not contain duplicate
elements. - Classes AbstractCollection, AbstractList, and
AbstractSet provide skeletal implementations of
the interfaces. - Concrete implementation classes extend these
abstract classes.
39The java.util CollectionltElementgt hierarchy
- Array-based list implementations extending
AbstractList - Java.util.ArrayList
- java.util.Vector.
- Array-based implementations grow automatically.
40The java.util CollectionltElementgt hierarchy
- java.util.LinkedList extends AbstractSequentialLis
t, which extends AbstractList. - It provides a doubly-linked list implementation.
- Its iterator() method returns an iterator that
allows bi-directional traversal of the linked
list.
41The java.util CollectionltElementgt hierarchy
interface
AbstractCollectionltElementgt
CollectionltElementgt
interface
AbstractListltElementgt
ListltElementgt
AbstractSequentialListltElementgt
LinkedListltElementgt
42Iterator interface
- Interface IteratorltElementgt specifies three
methods
public boolean hasNext () The iteration has more
elements.next public Element next () throws
NoSuchElementException The next element in the
iteration. Throws NoSuchElementException if
hasNext() is false public void remove ()
throws UnsupportedOperationException, IllegalSta
teException Removes from the underlying
collection the last element returned by the
iterator (optional operation). This method can be
called only once per call to next.
43Iterator interface
- Query hasNext is essentially the converse of our
Iterator method done. - Note that method next is not a proper query since
it changes the state of the iterator.
44Iterator interface
- We could implement next by accessing the current
element and then advancing the iterator
public Element next () Element temp
this.get() this.advance() return temp
45ListIterator interface
- ListIteratorltElementgt extends IteratorltElementgt.
- With a ListIterator,
- can traverse a list in either direction,
- can modify the list during iteration.
- It includes a method previous that serves as a
companion to next, and optional methods for
adding, removing, and setting list elements.
46Summary
- Providing both array-based and linked
implementations for List raises the question of
method performance. - Array-based access is in constant time.
- Linked based access requires linear time.
- Simple operations that iterate through each List
element become quadratic for linked
implementations when elements are accessed by
index.
47Summary
- Abstract index iterators.
- Iterators allow us to iterate through each
element of a List in linear time, regardless of
the implementing structure. - Iterator provides operations for traversing a
List while examining each List element.
48Summary
- The structure of each List implementation
dictates the algorithms used to traverse it - iterator implementations are tightly coupled to
the structure they traverse. - Provide each implementation with an inner class
that implements an appropriate iterator. - List client is provided with a factory method to
create iterators suitable for chosen
implementation.
49Summary
- List operations that take an index can be
overloaded with operations that take Iterator
instances, providing a richer List abstraction. - Care must be taken in specifying Iterator
behavior with regard to List modification. - We chose to mimic the behavior of indexes as
closely as possible. - deleting an element with a given index moves
the next element of the List up to that index
position.
50Summary
- Must exercise care when modifying a List
referenced by an Iterator by a means other than
with the Iterator. - For instance, if we delete a List element by
index, we assume that any Iterators referencing
the List become invalid.
51Summary
- Iterators give rise to the internal iterator
abstraction, where the implementor is in full
control of the traversal. - Defined a List method forEachDo that performed an
operation provided as an argument on each element
of the List.
52Summary
- Short tour of CollectionltElementgt interfaces and
abstractions in the standard Java package
java.util. - Collection interface provides a very rich
abstraction with several implementations. - List is an interface that extends Collection and
models a sequential collection in which elements
can be accessed by index. - java.util also provides iterators for Collections.