import java.util.ConcurrentModificationException;
import java.util.EmptyStackException;
import java.util.Iterator;

public class StackArray<Item> implements Iterable<Item>, Stack<Item>{  
                                                            
    private Item[] items;
    private int size;
    private int modCount;  
    
    public StackArray() {
        items = (Item[]) (new Object[1]); 
        size = 0; 
        modCount = 0;
    }
    
    public boolean isEmpty() {
        return (size == 0);
    }
    
    public int size() { 
        return size;
    }
    
    private void resize(int capacity) { 
        Item[] newArray = (Item[]) (new Object[capacity]);  
        for (int i = 0; i < size; i++) {   
            newArray[i] = items[i];
        }
        items = newArray;
    }
    
    public void push(Item item) {
        if (size == items.length)        
            resize( 2 * items.length );  
        items[size++] = item;
        modCount++;  
    }

    public Item peek() {
        return (this.isEmpty() ? null : items[size-1]);
    }
    
    public Item pop() {
       if (this.isEmpty())  
            throw new EmptyStackException();        
       Item item = items[--size];
       items[size] = null;   
       if (size != 0 && size == items.length/4)      
           resize(items.length/2);                     
       modCount++;
       return item;
    }
    
    public Iterator<Item> iterator() {
        return new Iterator<Item>() {
            private int nextPos = 0;
            private int savedModCount = modCount;  
           
            public boolean hasNext() {
                if (modCount != savedModCount) throw new ConcurrentModificationException();
                return nextPos < size;
            }

            public Item next() {
                if (modCount != savedModCount) throw new ConcurrentModificationException();
                return items[nextPos++];
            }
        };
    }

    public String toString() {
        String s = "";
        for (Item item : this)
            s += item.toString() + " ";
        return s;
    }
}


