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;
}
}