/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.collection; import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.control.Option; import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Predicate; /** * @author Pap Lőrinc, Daniel Dietrich */ abstract class AbstractQueue<T, Q extends AbstractQueue<T, Q>> implements Traversable<T> { /** * Removes an element from this Queue. * * @return a tuple containing the first element and the remaining elements of this Queue * @throws NoSuchElementException if this Queue is empty */ public Tuple2<T, Q> dequeue() { if (isEmpty()) { throw new NoSuchElementException("dequeue of empty " + getClass().getSimpleName()); } else { return Tuple.of(head(), tail()); } } /** * Removes an element from this Queue. * * @return {@code None} if this Queue is empty, otherwise {@code Some} {@code Tuple} containing the first element and the remaining elements of this Queue */ public Option<Tuple2<T, Q>> dequeueOption() { return isEmpty() ? Option.none() : Option.some(dequeue()); } /** * Enqueues a new element. * * @param element The new element * @return a new {@code Queue} instance, containing the new element */ public abstract Q enqueue(T element); /** * Enqueues the given elements. A queue has FIFO order, i.e. the first of the given elements is * the first which will be retrieved. * * @param elements Elements, may be empty * @return a new {@code Queue} instance, containing the new elements * @throws NullPointerException if elements is null */ @SuppressWarnings("unchecked") public Q enqueue(T... elements) { Objects.requireNonNull(elements, "elements is null"); return enqueueAll(List.of(elements)); } /** * Enqueues the given elements. A queue has FIFO order, i.e. the first of the given elements is * the first which will be retrieved. * * @param elements An Iterable of elements, may be empty * @return a new {@code Queue} instance, containing the new elements * @throws NullPointerException if elements is null */ public abstract Q enqueueAll(Iterable<? extends T> elements); /** * Returns the first element without modifying it. * * @return the first element * @throws NoSuchElementException if this Queue is empty */ public T peek() { if (isEmpty()) { throw new NoSuchElementException("peek of empty " + getClass().getSimpleName()); } else { return head(); } } /** * Returns the first element without modifying the Queue. * * @return {@code None} if this Queue is empty, otherwise a {@code Some} containing the first element */ public Option<T> peekOption() { return isEmpty() ? Option.none() : Option.some(peek()); } /** * Dual of {@linkplain #tail()}, returning all elements except the last. * * @return a new instance containing all elements except the last. * @throws UnsupportedOperationException if this is empty */ @Override public abstract Q init(); /** * Dual of {@linkplain #tailOption()}, returning all elements except the last as {@code Option}. * * @return {@code Some(Q)} or {@code None} if this is empty. */ @Override public Option<Q> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } /** * Drops the first element of a non-empty Traversable. * * @return A new instance of Traversable containing all elements except the first. * @throws UnsupportedOperationException if this is empty */ @Override public abstract Q tail(); @Override public Option<Q> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override @SuppressWarnings("unchecked") public Q retainAll(Iterable<? extends T> elements) { return Collections.retainAll((Q) this, elements); } @SuppressWarnings("unchecked") public Q removeAll(Iterable<? extends T> elements) { return Collections.removeAll((Q) this, elements); } @SuppressWarnings("unchecked") public Q removeAll(Predicate<? super T> predicate) { return Collections.removeAll((Q) this, predicate); } @Override public Q takeWhile(Predicate<? super T> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeUntil(predicate.negate()); } @Override public abstract Q takeUntil(Predicate<? super T> predicate); @SuppressWarnings("unchecked") @Override public Q peek(Consumer<? super T> action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return (Q) this; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } }