1 / 27

Computer Science 209

Computer Science 209. Software Development Iterators. The Problem. A collection contains elements Clients need to access the elements The collection should not expose its internal structure There may be multiple clients that need simultaneous access. The Solution.

tatum
Download Presentation

Computer Science 209

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Computer Science 209 Software Development Iterators

  2. The Problem • A collection contains elements • Clients need to access the elements • The collection should not expose its internal structure • There may be multiple clients that need simultaneous access

  3. The 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 collection and iterator classes, it is best to have a single iterator interface

  4. The Iterator Interface public interface Iterator<E>{ 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)

  5. Using an Iterator // add a bunch of objects to col Iterator<SomeType> iter = col.iterator(); Every collection class that supports an iterator must provide an iterator method. This method returns an instance of a class that implements the Iterator interface A sequence of elements anIterator aCollection

  6. Using an Iterator // add a bunch of objects to col Iterator<SomeType> iter = col.iterator(); while (iter.hasNext()){ SomeType obj = iter.next(); System.out.println(obj); } collection D D D iterator

  7. Using an Iterator // add a bunch of objects to col Iterator<SomeType> iter = col.iterator(); while (iter.hasNext()){ SomeType obj = iter.next(); System.out.println(obj); } collection D D D iterator

  8. Using an Iterator // add a bunch of objects to col Iterator<SomeType> iter = col.iterator(); while (iter.hasNext()){ SomeType obj = iter.next(); System.out.println(obj); } collection D D D iterator

  9. Using an Iterator // add a bunch of objects to col Iterator<SomeType> iter = col.iterator(); while (iter.hasNext()){ SomeType obj = iter.next(); System.out.println(obj); } collection D D D iterator

  10. Iterable and the for-each Loop // add a bunch of objects to col for (SomeType obj : col) System.out.println(obj); If col implements the Iterable interface, the client can use a for-each loop instead collection D D D iterator

  11. Use in AbstractCollection abstract public class AbstractCollection<E> implements Collection<E>{ public void clear(){ Iterator<E> iter = this.iterator(); while (iter.hasNext()){ iter.next(); iter.remove(); } } public boolean remove(Object o){ Iterator<E> iter = this.iterator(); while (iter.hasNext()) if (iter.next().equals(o)){ iter.remove(); return true; } return false; }

  12. Preconditions 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 collection’s mutators during the lifetime of that • iterator

  13. Error: Run Out of Elements // Add a bunch of objects to col Iterator<SomeType> iter = col.iterator(); while (iter.hasNext()){ SomeType obj = iter.next(); <blah blah blah> } SomeType obj = iter.next(); // This should cause an exception

  14. Error: Inconsistent Data // Add a bunch of objects to col Iterator<SomeType> 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

  15. An Iterator Implementation public interface TrueStack<E> extends Collection<E>{ public E pop(); public void push(E newElement); public E peek(); } <<Interface>> Iterable <<Interface>> Collection <<Interface>> TrueStack The iterator method is in the Iterable interface

  16. An Iterator Implementation public class ArrayStack<E> extends AbstractCollection<E> implements TrueStack<E>{ private List<E> list = new ArrayList<E>(); // Code for push, pop, peek, size, and add public Iterator<E> iterator(){ return list.iterator(); } } Problem: a list’s iterator supports the remove method

  17. An Iterator Implementation public class ArrayStack<E> extends AbstractCollection<E> implements TrueStack<E>{ private List<E> list = new ArrayList<E>(); // Code for push, pop, peek, size, and add // Code for the iterator method // Code for the class that implements the Iterator // interface } Define the iterator class as a private inner class.

  18. The Implementing Class public Iterator<E> iterator(){ return new StackIterator<E>(list); } private class StackIterator<E> implements Iterator<E>{ public boolean hasNext(){ return false; } public E next(){ return null; } public void remove(){ } } Nested within ArrayStack

  19. Tracking 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 iterator’s expected mod count as a precondition for next

  20. Data Within the Iterator private class StackIterator<E> implements Iterator<E>{ private int curPos, expectedModCount; private List<E> list; private StackIterator(List<E> list){ curPos = 0; expectedModCount = modCount; this.list = list; } // Other Iterator methods } Track the iterator’s current position and its notion of the mod count Note that the current position begins at the bottom of an ArrayStack (supports bottom to top traversal)

  21. Implementation of hasNext private class StackIterator<E> implements Iterator<E>{ private int curPos, expectedModCount; private List<E> list; public boolean hasNext(){ return curPos < list.size(); } }

  22. Implementation of next private class StackIterator<E> implements Iterator<E>{ private int curPos, expectedModCount; private List<E> list; 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 list.get(curPos – 1); } }

  23. Implementation of remove private class StackIterator<E> implements Iterator<E>{ private int curPos, expectedModCount; private List<E> list; public void remove(){ throw new UnsupportedOperationException( "remove not supported by Stack"); } } Removing objects with an iterator would violate the spirit of the TrueStack interface, which stipulates that items can only be removed from the top of the collection

  24. What about a Linked Stack? • Could try to use the same code for the iterator as in ArrayStack • Problem: get on linked list runs in linear time! private class StackIterator<E> implements Iterator<E>{ private int curPos, expectedModCount; private List<E> list; public E next(){ … return list.get(curPos – 1); } }

  25. Another Design Strategy • We used the list’s iterator earlier, but by exposing it to the client (Law of Demeter?) • Let’s use it, but wrap our own iterator object around it • That allows us to control what’s supported and what’s not

  26. The Implementing Class, v2 public Iterator<E> iterator(){ return new StackIterator<E>(list.iterator()); } private class StackIterator<E> implements Iterator<E>{ private Iterator<E> iter; private StackIterator(Iterator<E> iter){ this.iter = iter; } // Other methods } Nested within ArrayStack

  27. Other Methods private class StackIterator<E> implements Iterator<E>{ private Iterator<E> iter; public boolean hasNext(){ return iter.hasNext(); } public E next(){ return iter.next(); } public void remove(){ throw new UnsupportedOperationException( "remove not supported by Stack"); } }

More Related