Computer Science 209 Software Development Iterators Implementing equals

  • Slides: 23
Download presentation
Computer Science 209 Software Development Iterators

Computer Science 209 Software Development Iterators

Implementing equals for Sets public boolean equals(Object other){ if (this == other) return true;

Implementing equals for Sets public boolean equals(Object other){ if (this == other) return true; if (! (other instanceof Set)) return false; Set<E> other. Set = (Set)other; if (this. size() != other. Set. size()) return false; return this. contains. All(other. Set); } Works correctly, because order of items is not implied Worst-case quadratic running time

Implementing equals for Lists public boolean equals(Object other){ if (this == other) return true;

Implementing equals for Lists public boolean equals(Object other){ if (this == other) return true; if (! (other instanceof List)) return false; List<E> other. List = (List)other; if (this. size() != other. List. size()) return false; for (int i = 0; i < this. size(); i++) if (! this. get(i). equals(other. List. get(i))) return false; return true; } Works correctly by accounting for the order of the items get runs in constant time for Array. List but in linear time for Linked. List Worst-case quadratic running time for Linked. List. equals

Implementing equals with iterator public boolean equals(Object other){ if (this == other) return true;

Implementing equals with iterator public boolean equals(Object other){ if (this == other) return true; if (! (other instanceof List)) return false; List<E> other. List = (List)other; if (this. size() != other. List. size()) return false; Iterator<E> other. Iter = other. List. iterator(); for (E this. Element : this) if (! this. Element. equals(other. Iter. next())) return false; return true; } Works correctly by accounting for the order of the items next runs in constant time for any collection’s iterator Worst-case linear running time for equals with lists

The Iterator Interface public interface Iterator<E>{ public boolean has. Next() public E next() public

The Iterator Interface public interface Iterator<E>{ public boolean has. Next() public E next() public void remove() } remove deletes the item most recently accessed with next remove must be included in the implementing class, but need not be supported (can throw an Unsupported. Operation. Exception)

Using an Iterator // add a bunch of objects to col Iterator<Some. Type> iter

Using an Iterator // add a bunch of objects to col Iterator<Some. Type> 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 an. Iterator a. Collection

Using an Iterator // add a bunch of objects to col Iterator<Some. Type> iter

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

Using an Iterator // add a bunch of objects to col Iterator<Some. Type> iter

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

Using an Iterator // add a bunch of objects to col Iterator<Some. Type> iter

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

Using an Iterator // add a bunch of objects to col Iterator<Some. Type> iter

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

Iterable and the for-each Loop // add a bunch of objects to col for

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

Use in Abstract. Collection abstract public class Abstract. Collection<E> implements Collection<E>{ public void clear(){

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

Preconditions on Methods public boolean has. Next() public E next() has. Next has no

Preconditions on Methods public boolean has. Next() public E next() has. Next has no preconditions next has two preconditions: • has. Next returns true • the underlying collection has not been modified by one of that collection’s mutators during the lifetime of that iterator

Error: Run Out of Elements // Add a bunch of objects to col Iterator<Some.

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

Error: Inconsistent Data // Add a bunch of objects to col Iterator<Some. Type> iter

Error: Inconsistent Data // Add a bunch of objects to col Iterator<Some. Type> iter = col. iterator(); while (iter. has. Next()){ col. add(some. Item); Some. Type obj = iter. next(); } // This should cause an exception Using mutators in conjunction with iterators is a bad practice

An Iterator Implementation public interface True. Stack<E> extends Collection<E>{ public E pop(); public void

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

A Naïve Iterator Implementation public class Array. Stack<E> extends Abstract. Collection<E> implements True. Stack<E>{

A Naïve Iterator Implementation public class Array. Stack<E> extends Abstract. Collection<E> implements True. Stack<E>{ private List<E> list; // Code for constructors, push, pop, peek, and size public Iterator<E> iterator(){ return list. iterator(); } Problem: a list’s iterator supports the remove method This would violate the spirit of a stack

Another Design Strategy • By using the list’s iterator, we also expose the list

Another Design Strategy • By using the list’s iterator, we also expose the list to the client (violates the Law of Demeter) • Let’s continue to use it, but wrap our own iterator object around it • That allows us to control what’s supported and what’s not

An Iterator Implementation public class Array. Stack<E> extends Abstract. Collection<E> implements True. Stack<E>{ private

An Iterator Implementation public class Array. Stack<E> extends Abstract. Collection<E> implements True. Stack<E>{ private List<E> list; // Code for push, pop, peek, and size // Code for the iterator method // Code for the class that implements the Iterator // interface } Define the iterator class as a private inner class.

The Implementing Class public Iterator<E> iterator(){ return new Stack. Iterator<E>(this. iterator()); } private class

The Implementing Class public Iterator<E> iterator(){ return new Stack. Iterator<E>(this. iterator()); } private class Stack. Iterator<E> implements Iterator<E>{ public boolean has. Next(){ return false; } Nested within Array. Stack public E next(){ return null; } public void remove(){ } }

The Implementing Class public Iterator<E> iterator(){ return new Stack. Iterator<E>(list. iterator()); } private class

The Implementing Class public Iterator<E> iterator(){ return new Stack. Iterator<E>(list. iterator()); } private class Stack. Iterator<E> implements Iterator<E>{ private Iterator<E> iter; Nested within Array. Stack private Stack. Iterator(Iterator<E> iter){ this. iter = iter; } // Other methods } The stack iterator encapsulates the list iterator, hiding it from the client (proxy pattern)

Other Methods private class Stack. Iterator<E> implements Iterator<E>{ private Iterator<E> iter; public boolean has.

Other Methods private class Stack. Iterator<E> implements Iterator<E>{ private Iterator<E> iter; public boolean has. Next(){ return iter. has. Next(); } public E next(){ return iter. next(); } public void remove(){ throw new Unsupported. Operation. Exception( "remove not supported by stacks"); } } Must add javadoc with preconditions and code to check them

For Wednesday GUIs with Swing and AWT

For Wednesday GUIs with Swing and AWT