210 likes | 287 Views
Array Iterators. arrays in Java do not implement the Iterable interface; hence, arrays do not supply iterators if you implement a class that uses an array to hold a collection of objects and you want to provide an iterator for the collection, you need to implement your own iterator class
E N D
Array Iterators • arrays in Java do not implement the Iterable interface; hence, arrays do not supply iterators • if you implement a class that uses an array to hold a collection of objects and you want to provide an iterator for the collection, you need to implement your own iterator class • suppose we have a class X that has an array of Y objects
public class X implements Iterable<Y> { private Y[] yArray; // default constructor; creates yArray with // length 0 public X() { this(0); }
// constructor; creates yArray with // length numberOfY public X(int numberOfY) { if(numberOfY < 0) throw IllegalArgumentException("negative numberOfY"); this.yArray = new Y[numberOfY]; } // …
YIterator • because X implements Iterable, we must supply a method named iterator that supplies an iterator to a Y object • we will call the class that defines the iterator to a Y object YIterator
import java.util.Iterator; import java.util.NoSuchElementException; class YIterator implements Iterator<Y> { // attributes and constructors coming up... // Returns true if the iteration has more // elements. public boolean hasNext() { // ... }
// Returns the next element in the iteration. public Y next() { // ... } // Removes from the underlying collection the last // element returned by the iterator (optional // operation). public void remove() { // ... } }
Attributes • how does a YIterator • know if there are more elements? • return an element? • YIterator needs • an attribute that holds the reference or a copy of the array it is iterating over • an attribute that allows the iterator to return the next element • recall that array elements are indexed using an integer between 0 and (array length – 1)
Version 1: Reference to array class YIterator implements Iterator<Y> { private Y[] yArray; private int nextIndex; // precondition: arrayOfY not null public YIterator(Y[] arrayOfY) { this.yArray = arrayOfY; this.nextIndex = 0; }
Version 2: Copy of array class YIterator implements Iterator<Y> { private Y[] yArray; private int nextIndex; // precondition: arrayOfY not null public Yiterator(Y[] arrayOfY) { this.yArray = Arrays.copyOf(arrayOfY, arrayOfY.length); this.nextIndex = 0; }
hasNext • hasNext returns true if • the array yArray has an element at index nextIndexand • the element at index nextIndex is not null • recall that every array has a public attribute called length that gives the number of elements in the array • the array yArray has an element at index nextIndex only if nextIndex < yArray.length yArray.length == 5 yArray 0 1 2 3 4 if nextIndex > 4 yArray[nextIndex] throws ArrayIndexOurOfBoundsException
Array Memory Diagram for Objects Y[] yArray = new Y[5]; for(int i = 0; i < yArray.length; ++i) yArray[i] = new Y(); null 1200 null 1300 null 1400 null 1500 null 1600 references to objects of type Y
Array Memory Diagram for Objects float[] fArray = new float[5]; for(int i = 0; i < yArray.length; ++i) fArray[i] = (float)i; 0 0f 0 1f 0 2f 0 3f 0 4f instances of type int
// verbose version public boolean hasNext() { boolean result = false; if(this.nextIndex < this.yArray.length && this.yArray[nextIndex] != null) { result = true; } return result; }
// compact version public boolean hasNext() { return this.nextIndex < this.yArray.length && this.yArray[nextIndex] != null; }
if hasNext returns true then the client can call next to get the next element in the iteration • if hasNext returns false and the client calls next a NoSuchElementException is thrown • the next method needs to • check that hasNext is true; if not an exception is thrown • get the element at index nextIndex from the array yArray • move nextIndex to the next element in the array (increment)
// verbose version public Y next() { if(this.hasNext()) { Y nextY = this.yArray[this.nextIndex]; this.nextIndex++; return nextY; } else { throw new NoSuchElementException("no more elements"); } }
// compact version public Y next() { if(this.hasNext()) { return this.yArray[this.nextIndex++]; } else { throw new NoSuchElementException("no more elements"); } }
remove • remove is an optional operation • removes from the underlying collection the last element returned by the iterator • the client must first call the next method (to return an element) and then call remove • not as easy as removing the element indexed by nextIndex • if the iterator does not support remove it must throw an UnsupportedOperationException
public void remove() { throw new UnsupportedOperationException("Iterator does not support remove"); }
Removing an Element from an Array • removing an element from an array should reduce the length of the array by 1 • Java does not support resizable arrays • need to create a new array that is missing the removed element
A Question • suppose your iterator class supports remove and copies the array it is iterating over (slide 9) • what problem do you need to address when implementing remove?