package com.github.davidmoten.rtree.internal.util; import static com.github.davidmoten.guavamini.Optional.of; import java.util.Iterator; import com.github.davidmoten.guavamini.Optional; public final class ImmutableStack<T> implements Iterable<T> { private final Optional<T> head; private final Optional<ImmutableStack<T>> tail; private static ImmutableStack<?> EMPTY = new ImmutableStack<Object>(); public ImmutableStack(final T head, final ImmutableStack<T> tail) { this(of(head), of(tail)); } private ImmutableStack(Optional<T> head, Optional<ImmutableStack<T>> tail) { this.head = head; this.tail = tail; } public static <T> ImmutableStack<T> create(T t) { return new ImmutableStack<T>(of(t), of(ImmutableStack.<T> empty())); } public ImmutableStack() { this(Optional.<T> absent(), Optional.<ImmutableStack<T>> absent()); } @SuppressWarnings("unchecked") public static <S> ImmutableStack<S> empty() { return (ImmutableStack<S>) EMPTY; } public boolean isEmpty() { return !head.isPresent(); } public T peek() { // if (isEmpty()) // throw new RuntimeException("cannot peek on empty stack"); // else return this.head.get(); } public ImmutableStack<T> pop() { // if (isEmpty()) // throw new RuntimeException("cannot pop on empty stack"); // else return this.tail.get(); } public ImmutableStack<T> push(T value) { return new ImmutableStack<T>(value, this); } @Override public Iterator<T> iterator() { return new StackIterator<T>(this); } private static class StackIterator<U> implements Iterator<U> { private ImmutableStack<U> stack; public StackIterator(final ImmutableStack<U> stack) { this.stack = stack; } @Override public boolean hasNext() { return !this.stack.isEmpty(); } @Override public U next() { final U result = this.stack.peek(); this.stack = this.stack.pop(); return result; } @Override public void remove() { throw new RuntimeException("not supported"); } } }