import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.NoSuchElementException;

public class Tumpukan<E> {
    private final Deque<E> data = new ArrayDeque<>();

    /**
     * Menambahkan satu elemen ke puncak tumpukan.
     * Elemen null tidak diterima.
     */
    public void dorong(E elemen) {
        if (elemen == null) {
            throw new NullPointerException("elemen tidak boleh null");
        }
        data.push(elemen);
    }

    /**
     * Menambahkan seluruh elemen sumber ke puncak tumpukan, berurutan
     * dari elemen pertama hingga terakhir. Sumber hanya dibaca (producer),
     * sehingga Iterable<? extends E> diterima.
     */
    public void dorongSemua(Iterable<? extends E> sumber) {
        for (E elemen : sumber) {
            dorong(elemen);
        }
    }

    /**
     * Mengambil dan menghapus elemen puncak tumpukan.
     * Melempar NoSuchElementException bila tumpukan kosong.
     */
    public E ambil() {
        if (data.isEmpty()) {
            throw new NoSuchElementException("tumpukan kosong");
        }
        return data.pop();
    }

    /**
     * Memindahkan seluruh isi tumpukan ke koleksi tujuan, mulai dari
     * puncak hingga dasar. Tujuan hanya ditulis (consumer), sehingga
     * Collection<? super E> diterima. Tumpukan menjadi kosong setelah
     * pemanggilan berhasil.
     */
    public void ambilSemua(Collection<? super E> tujuan) {
        while (!data.isEmpty()) {
            tujuan.add(ambil());
        }
    }

    /**
     * Mengintip elemen puncak tanpa menghapusnya.
     * Melempar NoSuchElementException bila tumpukan kosong.
     */
    public E intip() {
        if (data.isEmpty()) {
            throw new NoSuchElementException("tumpukan kosong");
        }
        return data.peek();
    }

    /** Banyaknya elemen saat ini. */
    public int ukuran() {
        return data.size();
    }

    /** Benar bila tumpukan tidak memiliki elemen. */
    public boolean kosong() {
        return data.isEmpty();
    }
}
