import java.util.EmptyStackException; import java.lang.Iterable; import java.util.Iterator; import java.util.NoSuchElementException; public class Stack<E> implements Iterable<E> { // the value for default capacity private static final int DEFAULT_CAPACITY = 100; // the items stored in the stack private E[] items; // the index at the top of the stack private int top; // creates a stack with default size 100 public Stack() { this( DEFAULT_CAPACITY ); } // creates a stack with a given capacity public Stack( int capacity ) { items = (E[]) new Object[capacity]; top = 0; } public boolean isEmpty() { return top == 0; } public boolean isFull() { return top == items.length; } public boolean push(E value) { if (isFull()) { return false; } else { items[top] = value; top++; return true; } } public E pop() { if (isEmpty()) { throw new EmptyStackException(); } else { top--; return items[top]; } } private class StackIterator implements Iterator<E> { private int curPos; // index/position of next item to return public StackIterator() { curPos = 0; // first item to return on call to next() } @Override public boolean hasNext() { return curPos < top; } @Override public E next() { if (this.hasNext()) { E item = items[curPos]; curPos++; return item; } else { throw new NoSuchElementException(); } } @Override public void remove() { // Removes the *last* item given by next() based on these rules: // 1. can only call remove() if next() has been called // 2. cannot call remove() twice in a row // 3. the effect of remove() is to remove the last item given // In other words, we are *allowed* to call remove() if next() was // called right before; then need to wait for another call to next() // To implement these rules, add to StackIterator a boolean data member // that is turned ON/OFF to indicate whether it is safe to call remove() // Note again, that remove() removes the *last* item given by next() // *not* the item that next() is waiting to give } } // method of the stack -- required for Iterable @Override public Iterator<E> iterator() { return new StackIterator(); // return an object of our class } // using Iterator *explicitly* with while loop public String toString() { String str = ""; Iterator<E> iter = this.iterator(); // get iterator over me (the Stack) while ( iter.hasNext() ) { // as long as iterator has an item to give: E item = iter.next(); // get that item str = str + item + " "; // do something with the item } str = "[" + str.trim() + "]"; return str; } // using Iterator *implicitly* with enhanced for loop public String toString() { String str = ""; for ( E item : this ) { // for each item in me (the Stack): str = str + item + " "; // do something with the item } str = "[" + str.trim() + "]"; return str; } }