package de.skuzzle.polly.tools.collections; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.EmptyStackException; import java.util.Iterator; import java.util.NoSuchElementException; /** * Dynamic sized stack implementation based on a growing array. * * @author Simon Taddiken * @param <T> Type of elements in this stack. */ public class ArrayStack<T> implements Stack<T> { /** Initial size for no-args constructor. */ public final static int DEFAULT_SIZE = 16; private T[] stack; private int sp; private int modcount; /** * Creates a new ArrayStack with a {@link #DEFAULT_SIZE} of {@value #DEFAULT_SIZE}. */ public ArrayStack() { this(DEFAULT_SIZE); } /** * Creates a new ArrayStack with the given initial capacity. * @param capacity The initial capacity of the stack */ @SuppressWarnings("unchecked") public ArrayStack(int capacity) { this.stack = (T[]) new Object[capacity]; } /** * Creates a new ArrayStack by pushing all elements from the given collection onto * it. The elements will be pushed in order they are returned by the given * collection's iterator. * * @param c Initial elements. */ public ArrayStack(Collection<? extends T> c) { this(c.size()); for (final T t : c) { this.push(t); } } /** * Gets the element at position <code>i</code>. * @param i The index of the stack element to retrieve. * @return The element at the given position. */ public T get(int i) { if (i >= this.sp) { throw new IndexOutOfBoundsException(); } return this.stack[i]; } @SuppressWarnings("unchecked") private void ensureCapacity(int needed) { if (this.stack.length == needed) { final T[] tmp = (T[]) new Object[this.stack.length * 2]; System.arraycopy(this.stack, 0, tmp, 0, this.sp); this.stack = tmp; } } @Override public void push(T t) { ++this.modcount; this.ensureCapacity(this.sp + 1); this.stack[this.sp++] = t; } @Override public T pop() { if (this.isEmpty()) { throw new EmptyStackException(); } ++this.modcount; return this.stack[--this.sp]; } @Override public T peek() { if (this.isEmpty()) { throw new EmptyStackException(); } return this.stack[this.sp - 1]; } @Override public int size() { return this.sp; } @Override public boolean isEmpty() { return this.sp == 0; } @Override public Iterator<T> iterator() { return new Iterator<T>() { int i = sp; int modc = modcount; @Override public boolean hasNext() { return i > 0; } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } if (modc != modcount) { throw new ConcurrentModificationException(); } return stack[--i]; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }