/** * Returns a singleton {@code Stream}, i.e. a {@code Stream} of one element. * * @param element An element. * @param <T> The component type * @return A new Stream instance containing the given element */ static <T> Stream<T> of(T element) { return cons(element, Empty::instance); }
@Override default Stream<T> prepend(T element) { return cons(element, () -> this); }
static <T> Stream<T> create(java.util.Iterator<? extends T> iterator) { return iterator.hasNext() ? Stream.cons(iterator.next(), () -> create(iterator)) : Empty.instance(); } }
@Override default Stream<T> insert(int index, T element) { if (index < 0) { throw new IndexOutOfBoundsException("insert(" + index + ", e)"); } else if (index == 0) { return cons(element, () -> this); } else if (isEmpty()) { throw new IndexOutOfBoundsException("insert(" + index + ", e) on Nil"); } else { return cons(head(), () -> tail().insert(index - 1, element)); } }
@Override default Stream<T> peek(Consumer<? super T> action) { Objects.requireNonNull(action, "action is null"); if (isEmpty()) { return this; } else { final T head = head(); action.accept(head); return cons(head, () -> tail().peek(action)); } }
@Override default Stream<T> removeFirst(Predicate<T> predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return this; } else { final T head = head(); return predicate.test(head) ? tail() : cons(head, () -> tail().removeFirst(predicate)); } }
@Override default <U> Stream<U> map(Function<? super T, ? extends U> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return Empty.instance(); } else { return cons(mapper.apply(head()), () -> tail().map(mapper)); } }
@Override default Stream<T> removeAt(int index) { if (index < 0) { throw new IndexOutOfBoundsException("removeAt(" + index + ")"); } else if (index == 0) { return tail(); } else if (isEmpty()) { throw new IndexOutOfBoundsException("removeAt() on Nil"); } else { return cons(head(), () -> tail().removeAt(index - 1)); } }
@Override default Stream<T> replaceAll(T currentElement, T newElement) { if (isEmpty()) { return this; } else { final T head = head(); final T newHead = Objects.equals(head, currentElement) ? newElement : head; return cons(newHead, () -> tail().replaceAll(currentElement, newElement)); } }
private Cons<T> appendAll(Cons<T> stream, Function<? super Stream<T>, ? extends Stream<T>> mapper) { return (Cons<T>) Stream.cons(stream.head(), () -> { final Stream<T> tail = stream.tail(); return tail.isEmpty() ? mapper.apply(self) : appendAll((Cons<T>) tail, mapper); }); }
@Override default Stream<T> remove(T element) { if (isEmpty()) { return this; } else { final T head = head(); return Objects.equals(head, element) ? tail() : cons(head, () -> tail().remove(element)); } }
@Override default Stream<T> takeWhile(Predicate<? super T> predicate) { Objects.requireNonNull(predicate, "predicate is null"); if (isEmpty()) { return Empty.instance(); } else { final T head = head(); if (predicate.test(head)) { return cons(head, () -> tail().takeWhile(predicate)); } else { return Empty.instance(); } } }
@Override default Stream<T> init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty stream"); } else { final Stream<T> tail = tail(); if (tail.isEmpty()) { return Empty.instance(); } else { return cons(head(), tail::init); } } }
@Override default Stream<T> insertAll(int index, Iterable<? extends T> elements) { Objects.requireNonNull(elements, "elements is null"); if (index < 0) { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements)"); } else if (index == 0) { return isEmpty() ? Stream.ofAll(elements) : Stream.<T> ofAll(elements).appendAll(this); } else if (isEmpty()) { throw new IndexOutOfBoundsException("insertAll(" + index + ", elements) on Nil"); } else { return cons(head(), () -> tail().insertAll(index - 1, elements)); } }
@Override default Stream<T> slice(int beginIndex, int endIndex) { if (beginIndex >= endIndex || isEmpty()) { return empty(); } else { final int lowerBound = Math.max(beginIndex, 0); if (lowerBound == 0) { return cons(head(), () -> tail().slice(0, endIndex - 1)); } else { return tail().slice(lowerBound - 1, endIndex - 1); } } }
@Override default Stream<T> padTo(int length, T element) { if (length <= 0) { return this; } else if (isEmpty()) { return Stream.continually(element).take(length); } else { return cons(head(), () -> tail().padTo(length - 1, element)); } }
static <T> Stream<T> apply(io.vavr.collection.List<T> front, io.vavr.collection.List<T> rear, Stream<T> remaining) { if (remaining.isEmpty()) { return remaining; } else if (front.isEmpty()) { return apply(rear.reverse(), io.vavr.collection.List.empty(), remaining); } else { return Stream.cons(front.head(), () -> apply(front.tail(), rear.prepend(remaining.head()), remaining.tail())); } } }