Upload
miles-miles
View
237
Download
2
Tags:
Embed Size (px)
Citation preview
Learning Objectives
• Define the basic elements used in iterators• Use iterators to iterate over a collection• Implement iterators and the associated
generator classes for an ADT• Understand the design issues for iterators• Design iterators that support concurrency
Problem
• Consider the IntSet ADT introduced earlier• Let’s say you want to compute the sum of
elements in the set. How would you do it ?– Add a member function computeSum– Copy the rep to another array and return it– Add an indexing operation to the ADT– Add a new iterator abstraction
• Which method would you choose and why ?
Iteration Abstraction
• General way to iterate over the elements of an ADT without tying the iteration to a specific operation (e.g., summation)– Efficient in space and time (as far as possible)
For each element e of the ADT: Perform operation o on e
Implementation
• Implemented using two entities:
1. Generator: Keeps track of the state of the iteration and exposes operations to actually perform the iteration
2. Iterator: Operation of an ADT that returns a generator object to begin the iteration process
Iteration Abstraction: Generators
ADT
state 2
Client Code 1
Client Code 2
state 1
Generator objects
Client Code 3
Generators : Keeping track of State
• Objects that keep track of the state of the iteration in its rep– Implements the Iterator interface in Java– Consists of methods hasNext and next– next method throws NoSuchElementException
• Multiple generators can operate on an ADT
• Generators can be passed around to procedures
Generators: Examplepublic interface Iterator<T> {
public boolean hasNext()// EFFECTS: Returns true if there are more elements
to// yield, else returns false
public T next( ) throws NoSuchElementException// MODIFIES: this// EFFECTS: If there are more results to yield,// returns the next result and records the state of
this// Otherwise, throws NoSuchElementException
Iterator: Produces a generator
• Operation of an ADT or a stand-alone procedure that returns a generator object– Different iterators can produce different generators
(e.g., forward and reverse iterator)– Multiple calls to the iterator can produce different
generators (for local iteration)
• The specification of the iterator defines the behavior of the generator object it returns – add a requires clause at the end constraining its use
Iterator: IntSet Example
public class IntSet {... public Iterator<Integer> elements ( ) // EFFECTS: returns a generator that will produce // all the elements of this, each exactly once, // in arbitrary order. // REQUIRES: this must not be modified while // the generator is in use.}
Learning Objectives
• Define the basic elements used in iterators
• Use iterators to iterate over a collection
• Implement iterators and the associated generator classes for an ADT
• Design iterators that support concurrency
How do we use iterators ?
ADT (e.g., IntSet)
Has iterator methods that
return generator objects, e.g.,
elements
Generator object:
implements the Java iterator interface):1.hasNext
2.next
Step 1: Client invokes the iterator operation on ADT and stores the returned generator object
IntSet s = new IntSet(v);….Iterator g = s.elements();
Step 2: Perform the iteration using the hasNext and next methods of the generator object
while ( g.hasNext() ) { Integer o = g.next( );
int i = o.intValue();}
Optional Step: May pass the generator object to different procedures for doing the operation
e.g., int m = computeMax(g);
Example: Using Iteratorspublic static int max(Iterator<Integer> g) throws EmptyException{ // REQUIRES: g!=null && g contains only Integers // MODIFIES: g // EFFECTS: Throws EmptyException if no elements in g, otherwise return // the maximum element of the collection try{
int m = ( g.next() ).intValue() ; while ( g.hasNext() ) {
int x = ( g.next() ).intValue(); if (m < x) m = x;
} return m;
} catch( NoSuchElementException e) {
throw new EmptyException(“Comp.max”); }}
Some points on using Generators• Using code interacts with a generator via the iterator
interface (defined in java.util package)
• Using code must obey the constraint imposed on it by the iterator’s requires clause (given after the EFFECTS clause)
• Generators can be passed as arguments and returned as results by procedures
• Generators may be primed before using them in loops
• Generators may loop infinitely, e.g., list of prime numbers
In-class Exercise
• Write a procedure that iterates over the elements of the IntSet ADT and prints all Integers that exceed a certain threshold, max
How would you do this if you had an iterator that allowed you to choose elements that fall within a certain range, say, min and max.
Learning Objectives
• Define the basic elements used in iterators• Use iterators to iterate over a collection• Implement iterators and the associated
generator classes for an ADT• Understand the design issues for iterators• Design iterators that support concurrency
Implementing Iteratorspublic class IntSet { private vector<Integer> els; // The rep...
public Iterator<Integer> elements ( ) // EFFECTS: returns a generator object that will // produce all the elements of this, each exactly
// once, in arbitrary oder. // REQUIRES: this must not be modified while // the generator is in use.
return new IntSetGen(this);}
Implementing generators
• All generators implement Java’s iterator interface– Using code interacts with it through the interface– You must implement the methods hasNext and next
• Generator has access to the rep of the ADT– Must not be exposed to the using code
• Generator has its own rep to store the state of the iteration which also should not be exposed
IntSetGen: Scope
• IntSetGen is declared as a nested class within the IntSet ADT and it’s scope is private– Clients cannot create IntSetGen objects except
through the iterator method of the IntSet ADT– Clients cannot directly access any operation of
IntSetGen except through the iterator interface– IntSetGen has undeterred access to the private
methods of the IntSet including its rep
IntSetGen: Declarationpublic class IntSet { private vector<Integer> els; // The rep public Iterator<Integer> elements( ) { // Iterator // EFFECTS: … return new IntSetGen( this ); }
private static class IntSetGen implements Iterator<Integer>
{ // Generator object returned by elements }
IntSetGen: Rep and Constructorprivate static class IntSetGen implements Iterator<Integer>{
private int index;private IntSet s;
// ConstructorIntSetGen(IntSet is) {
// REQUIRES: is!= null // EFFECTS: Initializes the generator for a
// new iteration cycle s = is; index = 0;
}
Passed in by the elements() method of the IntSet ADT
IntSetGen: hasNext operation
public boolean hasNext( ){ // EFFECTS: If not reached the end // the elements vector, return true // otherwise, return false
if ( index == s.els.size( ) )return false;
elsereturn true;
}
IntSet ADT’sRep – can access this because it is declared as a nested class
IntSetGen: next operation
public Integer next( ) throws NoSuchElementException { // EFFECTS: If there is a next object, return it // Otherwise, throw the NoSuchElementException
if ( hasNext( ) )return s.els.get(index++);
else throw new
NoSuchElementException(“IntSet.elements”);}
Use the name of the iterator method that produced the generator object
In-class exercise
• Implement an Iterator for the IntSet ADT, to return all integers of the IntSet that satisfy a given critereon. The iterator takes as its argument a type Check with a public method:
public boolean checker(Integer) - that returns true if and only if the Integer satisfies the criteria
Assume that the Check class is given to you. Also, write the implementation of its associated generator object.
Learning Objectives
• Define the basic elements used in iterators• Use iterators to iterate over a collection• Implement iterators and the associated
generator classes for an ADT• Understand the design issues for iterators• Design iterators that support concurrency
Design Issues: Multiple Iterators
• Types may sometimes have multiple iterators
• Examples:– ForwardIterators, ReverseIterators for ordered
collections such as lists– Iterators that return elements satisfying a certain
critereon (say, within a specified range)– Iterators that perform some operation on their
elements prior to returning them (e.g., sorting)
Design Issues: Changes during Iteration
• Default behavior so far: Disallow changes during iteration (specified in post-REQUIRES clause)
• If changes are allowed, what are its semantics ?– State of iteration is what it was when the generator
was created (requires creating copy)– Iteration sequence changes when changes occur to
ADT (difficult to ensure consistency of state)• How do we reset iterator to go back in the collection ?• What if the current element is removed in a list ?
Design Issues: Can the generator itself change the ADT ?
• The generator can change the rep of the ADT as long as it does not change the abstraction– Example: An iterator that returns the elements of an
un-ordered collection such as set in sorted order may sort the collection during the process of iteration
• Iterator changes the abstraction exposed by ADT– This is usually best avoided unless there is a
compelling need. For example, iterating over a task list may itself spawn new tasks to be added to the list.
Testing Iterators
• Iterators are tested like procedures, except that they have paths in their specifications that are similar to loops in procedures– Should test for returning generators that produce
0, 1, 2 results/elements
• Generators are tested like any other ADT(Boundary conditions, aliasing etc.)
Learning Objectives
• Define the basic elements used in iterators• Use iterators to iterate over a collection• Implement iterators and the associated
generator classes for an ADT• Understand the design issues for iterators• Design iterators that support concurrency
Concurrent Iterators: Read only
• Assume that we want to iterate over a list in two separate threads, but without modifying it. Is this allowed ?– Yes, as long as we keep the generator objects
separate. i.e., we do not share generators– Each generator keeps track of where it is in the
iteration – no changes to the state of the ADT– We need to make the iterator method
synchronized (why ?)
Concurrent Iterators: Read-Write
Thread 1
Iterator<Integer> g = is.elements();
while ( g.hasNext() ) {Integer i = g.next();System.out.println(i + “ “);
}
Thread 2
is.add(1);is.add(2);is.add(3);is.add(4);is.remove(2);
No guarantees about what iterator returns
How to solve the concurrent iterator problem ?
• Disallow concurrent writes by requiring clients to take a lock before the iteration operation– Also disallows concurrent reads – performance !– Need to explicitly release lock when done
• Make a copy of the collection before iteration
• Throw a concurrent modification exception
Making a copy
• Create a copy of the list when you call the iterator method, and perform iteration over it– Need to ensure that copy operation is performed
in the iterator method in synchronized mode– Can be expensive to copy large lists in memory– Need to perform deep copy of elements to
disallow any modifications– Iterator may operate on stale version of collection
Concurrent modification exception
• Exception thrown when the ADT is modified concurrently with the iteration– Thrown to the thread that performs the iteration– Up to the thread what it wants to do with it– Only one exception per concurrent modification
will be thrown
• ConcurrentModification is a checked exception
CME: Usage public ... search (List list) { try { ListIterator iterator = list.listIterator(); while(iterator.hasNext()) { Object o = iterator.next(); //do something ... } } catch (ConcurrentModificationException concEx) { //handle this case, maybe just iterate the collection again return search(list); } }
CME: Implementation - 102 * The number of times this list has been structurally modified.03 * Structural modifications are those that change the size of the04 * list, or otherwise perturb it in such a fashion that iterations in05 * progress may yield incorrect results.…..15 * Use of this field by subclasses is optional. If a subclass16 * wishes to provide fail-fast iterators (and list iterators), then it17 * merely has to increment this field in its add(int, Object) and18 * remove(int) methods (and any other methods that it overrides19 * that result in structural modifications to the list). A single call to20 * add(int, Object) or remove(int) must add no more than21 * one to this field, or the iterators (and list iterators) will throw22 * bogus ConcurrentModificationExceptions. If an implementation23 * does not wish to provide fail-fast iterators, this field may be24 * ignored.25 */26 protected transient int modCount = 0;
CME: Implementation - 230 private class Itr implements Iterator<E> {31 int expectedModCount = modCount;32 33 public boolean hasNext() {34 // implementation omitted 35 }36 37 public E next() {38 checkForComodification();39 // implementation omitted 40 41 }42 43 private void checkForComodification() {44 if (modCount != expectedModCount)45 throw new ConcurrentModificationException();46 }47 }
Class Exercise
• Add a concurrent iterator to the IntSet ADT that throws a ConcurrentModificationException when another thread attempts to modify/remove from the set during the iteration.