user4060080
user4060080

Reputation:

How to use Iterator/Iterable in Java?

I want to make an iterator() method in my Prison class but to do that, I want to make a new class that will contain the boolean hasNext() and PrisonCell next() methods of an iterator that will implement a certain interface.

package iterator;
import java.util.Iterator;
public class Driver {

  public static void main(String args[]) {
    Prison prison= new Prison(5);
    Iterator<PrisonCell> iter;

    prison.addCell(new PrisonCell("A", 3));
    prison.addCell(new PrisonCell("B", 9));
    prison.addCell(new PrisonCell("C", 6));

    iter= prison.iterator(); //I want to make the iterator() method in my Prison class

    while (iter.hasNext())
      System.out.println(iter.next());
  }
    /**output here would be:
    Name: A, numPrisoners: 3
    Name: B, numPrisoners: 9
    Name: C, numPrisoners: 6
    **/

}



package iterator;
public class PrisonCell { //how would I implement the Iterable<> iterface here?

  private String name;
  private int numPrisoners;

  public PrisonCell(String name, int numPrisoners) {
    this.name= name;
    this.numPrisoners= numPrisoners;
  }

  public String toString() {
    return "Name: " + name + ", numPrisoners: " + numPrisoners;
  }

}



package iterator;
public class Prison{

    PrisonCell prisonCells[];
    int numPrisonCells;

    public Prison(int size) {
        prisonCells= new PrisonCell[size];
        numPrisoners= 0;
    }

    // just do nothing if the array is full
    public void addCell(PrisonCell newPrisonCell) {
        if (numPrisonCells < prisonCells.length)
            prisonCells[numPrisonCells++]= newPrisonCell;
    }

    //how do I write iterator() method here??
}

package iterator;
public class Iterator<PrisonCell>//is it supposed to implement an interface here?
//which fields here?
public Iterator() //constructor here
//I think boolean hasNext() and PrisonCell next() methods go here?

Upvotes: 0

Views: 4456

Answers (1)

Ted Hopp
Ted Hopp

Reputation: 234795

The Iterable interface is usually implemented by a collection of some sort. In your case, it is the Prison class, not the PrisonCell that could be declared to implement Iterable<PrisonCell>.* It would need to implement a single method: iterator(), which would return an Iterator<PrisonCell>.

What object to return? One easy way would be to simply wrap the array in a List and ask the List to return an Iterator:

public class Prison implements Iterable<PrisonCell> {
    PrisonCell prisonCells[];

    . . .

    public Iterator<PrisonCell> iterator() {
        return Arrays.asList(prisonCells).iterator();
    }
}

(You might consider changing prisonCells from a PrisonCell[] to a List<PrisonCell>; something I recommend. You could then ask it directly to return an Iterator.)

Alternatively, write your own class that implements the Iterator interface methods. (This is typically done by a private inner class of the collection class, since the iterator usually accesses the internal data structures of the collection—something that should not be exposed in a public api.) It should probably throw an exception for the remove() method, since that operation would normally not be supported for a collection backed by an object array. (The Iterator returned by a List constructed by Arrays.asList() behaves in this way.)

Here's a quick attempt at such an inner class. I wrote it under the assumption that the only the first numPrisonCells elements of the prisonCells array are valid:

public class Prison implements Iterable<PrisonCell> {

    PrisonCell prisonCells[];
    int numPrisonCells;

    . . .

    public Iterator<PrisonCell> iterator() {
        return new PrisonIterator();
    }

    private class PrisonIterator implements Iterator<PrisonCell> {
        private int index;

        PrisonIterator() {
            index = -1;
        }

        public boolean hasNext() {
            return index < numPrisonCells - 1;
        }

        public PrisonCell next() {
            if (index < numPrisonCells - 1) {
                return prisonCells[++index];
            } else {
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            // you could actually implement something here
            throw new UnsupportedOperationException();
        }
    }
}

Note that this is not a very robust iterator implementation; in particular, it could skip or repeat elements if the prisonCells array was modified during iteration. The Java Collections Framework addresses this by having each collection object maintain an internal long modification count and when each iterator is constructed, it initializes its own copy of the modification count. Then at each method call to the iterator, it checks to see that the collection's mod count matches its internal copy and, if not, throws a ConcurrentModificationException.

*Of course, you might want to have PrisonCell implement Iterable<Prisoner>. :)

Upvotes: 2

Related Questions