/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.collection;
import io.vavr.*;
import io.vavr.collection.Stream.Cons;
import io.vavr.collection.Stream.Empty;
import io.vavr.collection.StreamModule.*;
import io.vavr.control.Option;
import java.io.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collector;
import static io.vavr.collection.JavaConverters.ChangePolicy.IMMUTABLE;
import static io.vavr.collection.JavaConverters.ChangePolicy.MUTABLE;
/**
* An immutable {@code Stream} is lazy sequence of elements which may be infinitely long.
* Its immutability makes it suitable for concurrent programming.
* <p>
* A {@code Stream} is composed of a {@code head} element and a lazy evaluated {@code tail} {@code Stream}.
* <p>
* There are two implementations of the {@code Stream} interface:
*
* <ul>
* <li>{@link Empty}, which represents the empty {@code Stream}.</li>
* <li>{@link Cons}, which represents a {@code Stream} containing one or more elements.</li>
* </ul>
*
* Methods to obtain a {@code Stream}:
*
* <pre>
* <code>
* // factory methods
* Stream.empty() // = Stream.of() = Nil.instance()
* Stream.of(x) // = new Cons<>(x, Nil.instance())
* Stream.of(Object...) // e.g. Stream.of(1, 2, 3)
* Stream.ofAll(Iterable) // e.g. Stream.ofAll(List.of(1, 2, 3)) = 1, 2, 3
* Stream.ofAll(<primitive array>) // e.g. List.ofAll(1, 2, 3) = 1, 2, 3
*
* // int sequences
* Stream.from(0) // = 0, 1, 2, 3, ...
* Stream.range(0, 3) // = 0, 1, 2
* Stream.rangeClosed(0, 3) // = 0, 1, 2, 3
*
* // generators
* Stream.cons(Object, Supplier) // e.g. Stream.cons(current, () -> next(current));
* Stream.continually(Supplier) // e.g. Stream.continually(Math::random);
* Stream.iterate(Object, Function)// e.g. Stream.iterate(1, i -> i * 2);
* </code>
* </pre>
*
* Factory method applications:
*
* <pre>
* <code>
* Stream<Integer> s1 = Stream.of(1);
* Stream<Integer> s2 = Stream.of(1, 2, 3);
* // = Stream.of(new Integer[] {1, 2, 3});
*
* Stream<int[]> s3 = Stream.ofAll(1, 2, 3);
* Stream<List<Integer>> s4 = Stream.ofAll(List.of(1, 2, 3));
*
* Stream<Integer> s5 = Stream.ofAll(1, 2, 3);
* Stream<Integer> s6 = Stream.ofAll(List.of(1, 2, 3));
*
* // cuckoo's egg
* Stream<Integer[]> s7 = Stream.<Integer[]> of(new Integer[] {1, 2, 3});
* </code>
* </pre>
*
* Example: Generating prime numbers
*
* <pre>
* <code>
* // = Stream(2L, 3L, 5L, 7L, ...)
* Stream.iterate(2L, PrimeNumbers::nextPrimeFrom)
*
* // helpers
*
* static long nextPrimeFrom(long num) {
* return Stream.from(num + 1).find(PrimeNumbers::isPrime).get();
* }
*
* static boolean isPrime(long num) {
* return !Stream.rangeClosed(2L, (long) Math.sqrt(num)).exists(d -> num % d == 0);
* }
* </code>
* </pre>
*
* See Okasaki, Chris: <em>Purely Functional Data Structures</em> (p. 34 ff.). Cambridge, 2003.
*
* @param <T> component type of this Stream
* @author Daniel Dietrich, Jörgen Andersson, Ruslan Sennov
*/
public interface Stream<T> extends LinearSeq<T> {
long serialVersionUID = 1L;
/**
* Returns a {@link java.util.stream.Collector} which may be used in conjunction with
* {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link Stream}.
*
* @param <T> Component type of the Stream.
* @return A io.vavr.collection.Stream Collector.
*/
static <T> Collector<T, ArrayList<T>, Stream<T>> collector() {
final Supplier<ArrayList<T>> supplier = ArrayList::new;
final BiConsumer<ArrayList<T>, T> accumulator = ArrayList::add;
final BinaryOperator<ArrayList<T>> combiner = (left, right) -> {
left.addAll(right);
return left;
};
final Function<ArrayList<T>, Stream<T>> finisher = Stream::ofAll;
return Collector.of(supplier, accumulator, combiner, finisher);
}
/**
* Lazily creates a Stream in O(1) which traverses along the concatenation of the given iterables.
*
* @param iterables The iterables
* @param <T> Component type.
* @return A new {@code Stream}
*/
@SuppressWarnings("varargs")
@SafeVarargs
static <T> Stream<T> concat(Iterable<? extends T>... iterables) {
return Iterator.concat(iterables).toStream();
}
/**
* Lazily creates a Stream in O(1) which traverses along the concatenation of the given iterables.
*
* @param iterables The iterable of iterables
* @param <T> Component type.
* @return A new {@code Stream}
*/
static <T> Stream<T> concat(Iterable<? extends Iterable<? extends T>> iterables) {
return Iterator.<T> concat(iterables).toStream();
}
/**
* Returns an infinitely long Stream of {@code int} values starting from {@code from}.
* <p>
* The {@code Stream} extends to {@code Integer.MIN_VALUE} when passing {@code Integer.MAX_VALUE}.
*
* @param value a start int value
* @return a new Stream of int values starting from {@code from}
*/
static Stream<Integer> from(int value) {
return Stream.ofAll(Iterator.from(value));
}
/**
* Returns an infinite long Stream of {@code int} values starting from {@code value} and spaced by {@code step}.
* <p>
* The {@code Stream} extends to {@code Integer.MIN_VALUE} when passing {@code Integer.MAX_VALUE}.
*
* @param value a start int value
* @param step the step by which to advance on each next value
* @return a new {@code Stream} of int values starting from {@code from}
*/
static Stream<Integer> from(int value, int step) {
return Stream.ofAll(Iterator.from(value, step));
}
/**
* Returns an infinitely long Stream of {@code long} values starting from {@code from}.
* <p>
* The {@code Stream} extends to {@code Integer.MIN_VALUE} when passing {@code Long.MAX_VALUE}.
*
* @param value a start long value
* @return a new Stream of long values starting from {@code from}
*/
static Stream<Long> from(long value) {
return Stream.ofAll(Iterator.from(value));
}
/**
* Returns an infinite long Stream of {@code long} values starting from {@code value} and spaced by {@code step}.
* <p>
* The {@code Stream} extends to {@code Long.MIN_VALUE} when passing {@code Long.MAX_VALUE}.
*
* @param value a start long value
* @param step the step by which to advance on each next value
* @return a new {@code Stream} of long values starting from {@code from}
*/
static Stream<Long> from(long value, long step) {
return Stream.ofAll(Iterator.from(value, step));
}
/**
* Generates an (theoretically) infinitely long Stream using a value Supplier.
*
* @param supplier A Supplier of Stream values
* @param <T> value type
* @return A new Stream
*/
static <T> Stream<T> continually(Supplier<? extends T> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return Stream.ofAll(Iterator.continually(supplier));
}
/**
* Generates a (theoretically) infinitely long Stream using a function to calculate the next value
* based on the previous.
*
* @param seed The first value in the Stream
* @param f A function to calculate the next value based on the previous
* @param <T> value type
* @return A new Stream
*/
static <T> Stream<T> iterate(T seed, Function<? super T, ? extends T> f) {
Objects.requireNonNull(f, "f is null");
return Stream.ofAll(Iterator.iterate(seed, f));
}
/**
* Constructs a Stream of a head element and a tail supplier.
*
* @param head The head element of the Stream
* @param tailSupplier A supplier of the tail values. To end the stream, return {@link Stream#empty}.
* @param <T> value type
* @return A new Stream
*/
@SuppressWarnings("unchecked")
static <T> Stream<T> cons(T head, Supplier<? extends Stream<? extends T>> tailSupplier) {
Objects.requireNonNull(tailSupplier, "tailSupplier is null");
return new ConsImpl<>(head, (Supplier<Stream<T>>) tailSupplier);
}
/**
* Returns the single instance of Nil. Convenience method for {@code Nil.instance()}.
* <p>
* Note: this method intentionally returns type {@code Stream} and not {@code Nil}. This comes handy when folding.
* If you explicitly need type {@code Nil} use {@linkplain Empty#instance()}.
*
* @param <T> Component type of Nil, determined by type inference in the particular context.
* @return The empty list.
*/
static <T> Stream<T> empty() {
return Empty.instance();
}
/**
* Narrows a widened {@code Stream<? extends T>} to {@code Stream<T>}
* by performing a type-safe cast. This is eligible because immutable/read-only
* collections are covariant.
*
* @param stream A {@code Stream}.
* @param <T> Component type of the {@code Stream}.
* @return the given {@code stream} instance as narrowed type {@code Stream<T>}.
*/
@SuppressWarnings("unchecked")
static <T> Stream<T> narrow(Stream<? extends T> stream) {
return (Stream<T>) stream;
}
/**
* 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);
}
/**
* Creates a Stream of the given elements.
*
* <pre><code> Stream.of(1, 2, 3, 4)
* = Nil.instance().prepend(4).prepend(3).prepend(2).prepend(1)
* = new Cons(1, new Cons(2, new Cons(3, new Cons(4, Nil.instance()))))</code></pre>
*
* @param <T> Component type of the Stream.
* @param elements Zero or more elements.
* @return A list containing the given elements in the same order.
*/
@SafeVarargs
static <T> Stream<T> of(T... elements) {
Objects.requireNonNull(elements, "elements is null");
return Stream.ofAll(new Iterator<T>() {
int i = 0;
@Override
public boolean hasNext() {
return i < elements.length;
}
@Override
public T next() {
return elements[i++];
}
});
}
/**
* Returns a Stream containing {@code n} values of a given Function {@code f}
* over a range of integer values from 0 to {@code n - 1}.
*
* @param <T> Component type of the Stream
* @param n The number of elements in the Stream
* @param f The Function computing element values
* @return A Stream consisting of elements {@code f(0),f(1), ..., f(n - 1)}
* @throws NullPointerException if {@code f} is null
*/
static <T> Stream<T> tabulate(int n, Function<? super Integer, ? extends T> f) {
Objects.requireNonNull(f, "f is null");
return Stream.ofAll(io.vavr.collection.Collections.tabulate(n, f));
}
/**
* Returns a Stream containing {@code n} values supplied by a given Supplier {@code s}.
*
* @param <T> Component type of the Stream
* @param n The number of elements in the Stream
* @param s The Supplier computing element values
* @return A Stream of size {@code n}, where each element contains the result supplied by {@code s}.
* @throws NullPointerException if {@code s} is null
*/
static <T> Stream<T> fill(int n, Supplier<? extends T> s) {
Objects.requireNonNull(s, "s is null");
return Stream.ofAll(io.vavr.collection.Collections.fill(n, s));
}
/**
* Creates a Stream of the given elements.
*
* @param <T> Component type of the Stream.
* @param elements An Iterable of elements.
* @return A Stream containing the given elements in the same order.
*/
@SuppressWarnings("unchecked")
static <T> Stream<T> ofAll(Iterable<? extends T> elements) {
Objects.requireNonNull(elements, "elements is null");
if (elements instanceof Stream) {
return (Stream<T>) elements;
} else {
return StreamFactory.create(elements.iterator());
}
}
/**
* Creates a Stream that contains the elements of the given {@link java.util.stream.Stream}.
*
* @param javaStream A {@link java.util.stream.Stream}
* @param <T> Component type of the Stream.
* @return A Stream containing the given elements in the same order.
*/
static <T> Stream<T> ofAll(java.util.stream.Stream<? extends T> javaStream) {
Objects.requireNonNull(javaStream, "javaStream is null");
return StreamFactory.create(javaStream.iterator());
}
/**
* Creates a Stream from boolean values.
*
* @param elements boolean values
* @return A new Stream of Boolean values
* @throws NullPointerException if elements is null
*/
static Stream<Boolean> ofAll(boolean... elements) {
Objects.requireNonNull(elements, "elements is null");
return Stream.ofAll(Iterator.ofAll(elements));
}
/**
* Creates a Stream from byte values.
*
* @param elements byte values
* @return A new Stream of Byte values
* @throws NullPointerException if elements is null
*/
static Stream<Byte> ofAll(byte... elements) {
Objects.requireNonNull(elements, "elements is null");
return Stream.ofAll(Iterator.ofAll(elements));
}
/**
* Creates a Stream from char values.
*
* @param elements char values
* @return A new Stream of Character values
* @throws NullPointerException if elements is null
*/
static Stream<Character> ofAll(char... elements) {
Objects.requireNonNull(elements, "elements is null");
return Stream.ofAll(Iterator.ofAll(elements));
}
/**
* Creates a Stream values double values.
*
* @param elements double values
* @return A new Stream of Double values
* @throws NullPointerException if elements is null
*/
static Stream<Double> ofAll(double... elements) {
Objects.requireNonNull(elements, "elements is null");
return Stream.ofAll(Iterator.ofAll(elements));
}
/**
* Creates a Stream from float values.
*
* @param elements float values
* @return A new Stream of Float values
* @throws NullPointerException if elements is null
*/
static Stream<Float> ofAll(float... elements) {
Objects.requireNonNull(elements, "elements is null");
return Stream.ofAll(Iterator.ofAll(elements));
}
/**
* Creates a Stream from int values.
*
* @param elements int values
* @return A new Stream of Integer values
* @throws NullPointerException if elements is null
*/
static Stream<Integer> ofAll(int... elements) {
Objects.requireNonNull(elements, "elements is null");
return Stream.ofAll(Iterator.ofAll(elements));
}
/**
* Creates a Stream from long values.
*
* @param elements long values
* @return A new Stream of Long values
* @throws NullPointerException if elements is null
*/
static Stream<Long> ofAll(long... elements) {
Objects.requireNonNull(elements, "elements is null");
return Stream.ofAll(Iterator.ofAll(elements));
}
/**
* Creates a Stream from short values.
*
* @param elements short values
* @return A new Stream of Short values
* @throws NullPointerException if elements is null
*/
static Stream<Short> ofAll(short... elements) {
Objects.requireNonNull(elements, "elements is null");
return Stream.ofAll(Iterator.ofAll(elements));
}
static Stream<Character> range(char from, char toExclusive) {
return Stream.ofAll(Iterator.range(from, toExclusive));
}
static Stream<Character> rangeBy(char from, char toExclusive, int step) {
return Stream.ofAll(Iterator.rangeBy(from, toExclusive, step));
}
@GwtIncompatible
static Stream<Double> rangeBy(double from, double toExclusive, double step) {
return Stream.ofAll(Iterator.rangeBy(from, toExclusive, step));
}
/**
* Creates a Stream of int numbers starting from {@code from}, extending to {@code toExclusive - 1}.
* <p>
* Examples:
* <pre>
* <code>
* Stream.range(0, 0) // = Stream()
* Stream.range(2, 0) // = Stream()
* Stream.range(-2, 2) // = Stream(-2, -1, 0, 1)
* </code>
* </pre>
*
* @param from the first number
* @param toExclusive the last number + 1
* @return a range of int values as specified or {@code Nil} if {@code from >= toExclusive}
*/
static Stream<Integer> range(int from, int toExclusive) {
return Stream.ofAll(Iterator.range(from, toExclusive));
}
/**
* Creates a Stream of int numbers starting from {@code from}, extending to {@code toExclusive - 1},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Stream.rangeBy(1, 3, 1) // = Stream(1, 2)
* Stream.rangeBy(1, 4, 2) // = Stream(1, 3)
* Stream.rangeBy(4, 1, -2) // = Stream(4, 2)
* Stream.rangeBy(4, 1, 2) // = Stream()
* </code>
* </pre>
*
* @param from the first number
* @param toExclusive the last number + 1
* @param step the step
* @return a range of long values as specified or {@code Nil} if<br>
* {@code from >= toInclusive} and {@code step > 0} or<br>
* {@code from <= toInclusive} and {@code step < 0}
* @throws IllegalArgumentException if {@code step} is zero
*/
static Stream<Integer> rangeBy(int from, int toExclusive, int step) {
return Stream.ofAll(Iterator.rangeBy(from, toExclusive, step));
}
/**
* Creates a Stream of long numbers starting from {@code from}, extending to {@code toExclusive - 1}.
* <p>
* Examples:
* <pre>
* <code>
* Stream.range(0L, 0L) // = Stream()
* Stream.range(2L, 0L) // = Stream()
* Stream.range(-2L, 2L) // = Stream(-2L, -1L, 0L, 1L)
* </code>
* </pre>
*
* @param from the first number
* @param toExclusive the last number + 1
* @return a range of long values as specified or {@code Nil} if {@code from >= toExclusive}
*/
static Stream<Long> range(long from, long toExclusive) {
return Stream.ofAll(Iterator.range(from, toExclusive));
}
/**
* Creates a Stream of long numbers starting from {@code from}, extending to {@code toExclusive - 1},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Stream.rangeBy(1L, 3L, 1L) // = Stream(1L, 2L)
* Stream.rangeBy(1L, 4L, 2L) // = Stream(1L, 3L)
* Stream.rangeBy(4L, 1L, -2L) // = Stream(4L, 2L)
* Stream.rangeBy(4L, 1L, 2L) // = Stream()
* </code>
* </pre>
*
* @param from the first number
* @param toExclusive the last number + 1
* @param step the step
* @return a range of long values as specified or {@code Nil} if<br>
* {@code from >= toInclusive} and {@code step > 0} or<br>
* {@code from <= toInclusive} and {@code step < 0}
* @throws IllegalArgumentException if {@code step} is zero
*/
static Stream<Long> rangeBy(long from, long toExclusive, long step) {
return Stream.ofAll(Iterator.rangeBy(from, toExclusive, step));
}
static Stream<Character> rangeClosed(char from, char toInclusive) {
return Stream.ofAll(Iterator.rangeClosed(from, toInclusive));
}
static Stream<Character> rangeClosedBy(char from, char toInclusive, int step) {
return Stream.ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
}
@GwtIncompatible
static Stream<Double> rangeClosedBy(double from, double toInclusive, double step) {
return Stream.ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
}
/**
* Creates a Stream of int numbers starting from {@code from}, extending to {@code toInclusive}.
* <p>
* Examples:
* <pre>
* <code>
* Stream.rangeClosed(0, 0) // = Stream(0)
* Stream.rangeClosed(2, 0) // = Stream()
* Stream.rangeClosed(-2, 2) // = Stream(-2, -1, 0, 1, 2)
* </code>
* </pre>
*
* @param from the first number
* @param toInclusive the last number
* @return a range of int values as specified or {@code Nil} if {@code from > toInclusive}
*/
static Stream<Integer> rangeClosed(int from, int toInclusive) {
return Stream.ofAll(Iterator.rangeClosed(from, toInclusive));
}
/**
* Creates a Stream of int numbers starting from {@code from}, extending to {@code toInclusive},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Stream.rangeClosedBy(1, 3, 1) // = Stream(1, 2, 3)
* Stream.rangeClosedBy(1, 4, 2) // = Stream(1, 3)
* Stream.rangeClosedBy(4, 1, -2) // = Stream(4, 2)
* Stream.rangeClosedBy(4, 1, 2) // = Stream()
* </code>
* </pre>
*
* @param from the first number
* @param toInclusive the last number
* @param step the step
* @return a range of int values as specified or {@code Nil} if<br>
* {@code from > toInclusive} and {@code step > 0} or<br>
* {@code from < toInclusive} and {@code step < 0}
* @throws IllegalArgumentException if {@code step} is zero
*/
static Stream<Integer> rangeClosedBy(int from, int toInclusive, int step) {
return Stream.ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
}
/**
* Creates a Stream of long numbers starting from {@code from}, extending to {@code toInclusive}.
* <p>
* Examples:
* <pre>
* <code>
* Stream.rangeClosed(0L, 0L) // = Stream(0L)
* Stream.rangeClosed(2L, 0L) // = Stream()
* Stream.rangeClosed(-2L, 2L) // = Stream(-2L, -1L, 0L, 1L, 2L)
* </code>
* </pre>
*
* @param from the first number
* @param toInclusive the last number
* @return a range of long values as specified or {@code Nil} if {@code from > toInclusive}
*/
static Stream<Long> rangeClosed(long from, long toInclusive) {
return Stream.ofAll(Iterator.rangeClosed(from, toInclusive));
}
/**
* Creates a Stream of long numbers starting from {@code from}, extending to {@code toInclusive},
* with {@code step}.
* <p>
* Examples:
* <pre>
* <code>
* Stream.rangeClosedBy(1L, 3L, 1L) // = Stream(1L, 2L, 3L)
* Stream.rangeClosedBy(1L, 4L, 2L) // = Stream(1L, 3L)
* Stream.rangeClosedBy(4L, 1L, -2L) // = Stream(4L, 2L)
* Stream.rangeClosedBy(4L, 1L, 2L) // = Stream()
* </code>
* </pre>
*
* @param from the first number
* @param toInclusive the last number
* @param step the step
* @return a range of int values as specified or {@code Nil} if<br>
* {@code from > toInclusive} and {@code step > 0} or<br>
* {@code from < toInclusive} and {@code step < 0}
* @throws IllegalArgumentException if {@code step} is zero
*/
static Stream<Long> rangeClosedBy(long from, long toInclusive, long step) {
return Stream.ofAll(Iterator.rangeClosedBy(from, toInclusive, step));
}
/**
* Transposes the rows and columns of a {@link Stream} matrix.
*
* @param <T> matrix element type
* @param matrix to be transposed.
* @return a transposed {@link Stream} matrix.
* @throws IllegalArgumentException if the row lengths of {@code matrix} differ.
* <p>
* ex: {@code
* Stream.transpose(Stream(Stream(1,2,3), Stream(4,5,6))) → Stream(Stream(1,4), Stream(2,5), Stream(3,6))
* }
*/
static <T> Stream<Stream<T>> transpose(Stream<Stream<T>> matrix) {
return io.vavr.collection.Collections.transpose(matrix, Stream::ofAll, Stream::of);
}
/**
* Creates a Stream from a seed value and a function.
* The function takes the seed at first.
* The function should return {@code None} when it's
* done generating the Stream, otherwise {@code Some} {@code Tuple}
* of the element for the next call and the value to add to the
* resulting Stream.
* <p>
* Example:
* <pre>
* <code>
* Stream.unfoldRight(10, x -> x == 0
* ? Option.none()
* : Option.of(new Tuple2<>(x, x-1)));
* // Stream(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
* </code>
* </pre>
*
* @param <T> type of seeds
* @param <U> type of unfolded values
* @param seed the start value for the iteration
* @param f the function to get the next step of the iteration
* @return a Stream with the values built up by the iteration
* @throws NullPointerException if {@code f} is null
*/
static <T, U> Stream<U> unfoldRight(T seed, Function<? super T, Option<Tuple2<? extends U, ? extends T>>> f) {
return Iterator.unfoldRight(seed, f).toStream();
}
/**
* Creates a Stream from a seed value and a function.
* The function takes the seed at first.
* The function should return {@code None} when it's
* done generating the Stream, otherwise {@code Some} {@code Tuple}
* of the value to add to the resulting Stream and
* the element for the next call.
* <p>
* Example:
* <pre>
* <code>
* Stream.unfoldLeft(10, x -> x == 0
* ? Option.none()
* : Option.of(new Tuple2<>(x-1, x)));
* // Stream(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
* </code>
* </pre>
*
* @param <T> type of seeds
* @param <U> type of unfolded values
* @param seed the start value for the iteration
* @param f the function to get the next step of the iteration
* @return a Stream with the values built up by the iteration
* @throws NullPointerException if {@code f} is null
*/
static <T, U> Stream<U> unfoldLeft(T seed, Function<? super T, Option<Tuple2<? extends T, ? extends U>>> f) {
return Iterator.unfoldLeft(seed, f).toStream();
}
/**
* Creates a Stream from a seed value and a function.
* The function takes the seed at first.
* The function should return {@code None} when it's
* done generating the Stream, otherwise {@code Some} {@code Tuple}
* of the value to add to the resulting Stream and
* the element for the next call.
* <p>
* Example:
* <pre>
* <code>
* Stream.unfold(10, x -> x == 0
* ? Option.none()
* : Option.of(new Tuple2<>(x-1, x)));
* // Stream(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
* </code>
* </pre>
*
* @param <T> type of seeds and unfolded values
* @param seed the start value for the iteration
* @param f the function to get the next step of the iteration
* @return a Stream with the values built up by the iteration
* @throws NullPointerException if {@code f} is null
*/
static <T> Stream<T> unfold(T seed, Function<? super T, Option<Tuple2<? extends T, ? extends T>>> f) {
return Iterator.unfold(seed, f).toStream();
}
/**
* Repeats an element infinitely often.
*
* @param t An element
* @param <T> Element type
* @return A new Stream containing infinite {@code t}'s.
*/
static <T> Stream<T> continually(T t) {
return Stream.ofAll(Iterator.continually(t));
}
@Override
default Stream<T> append(T element) {
return isEmpty() ? Stream.of(element) : new AppendElements<>(head(), io.vavr.collection.Queue.of(element), this::tail);
}
@Override
default Stream<T> appendAll(Iterable<? extends T> elements) {
Objects.requireNonNull(elements, "elements is null");
if (Collections.isEmpty(elements)) {
return this;
} else if (isEmpty()) {
return Stream.ofAll(elements);
} else {
return Stream.ofAll(Iterator.concat(this, elements));
}
}
/**
* Appends itself to the end of stream with {@code mapper} function.
* <p>
* <strong>Example:</strong>
* <p>
* Well known Scala code for Fibonacci infinite sequence
* <pre>
* <code>
* val fibs:Stream[Int] = 0 #:: 1 #:: (fibs zip fibs.tail).map{ t => t._1 + t._2 }
* </code>
* </pre>
* can be transformed to
* <pre>
* <code>
* Stream.of(0, 1).appendSelf(self -> self.zip(self.tail()).map(t -> t._1 + t._2));
* </code>
* </pre>
*
* @param mapper an mapper
* @return a new Stream
*/
default Stream<T> appendSelf(Function<? super Stream<T>, ? extends Stream<T>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return isEmpty() ? this : new AppendSelf<>((Cons<T>) this, mapper).stream();
}
@GwtIncompatible
@Override
default java.util.List<T> asJava() {
return JavaConverters.asJava(this, IMMUTABLE);
}
@GwtIncompatible
@Override
default Stream<T> asJava(Consumer<? super java.util.List<T>> action) {
return Collections.asJava(this, action, IMMUTABLE);
}
@GwtIncompatible
@Override
default java.util.List<T> asJavaMutable() {
return JavaConverters.asJava(this, MUTABLE);
}
@GwtIncompatible
@Override
default Stream<T> asJavaMutable(Consumer<? super java.util.List<T>> action) {
return Collections.asJava(this, action, MUTABLE);
}
@Override
default <R> Stream<R> collect(PartialFunction<? super T, ? extends R> partialFunction) {
return ofAll(iterator().<R> collect(partialFunction));
}
@Override
default Stream<Stream<T>> combinations() {
return Stream.rangeClosed(0, length()).map(this::combinations).flatMap(Function.identity());
}
@Override
default Stream<Stream<T>> combinations(int k) {
return Combinations.apply(this, Math.max(k, 0));
}
@Override
default Iterator<Stream<T>> crossProduct(int power) {
return io.vavr.collection.Collections.crossProduct(Stream.empty(), this, power);
}
/**
* Repeat the elements of this Stream infinitely.
* <p>
* Example:
* <pre>
* <code>
* // = 1, 2, 3, 1, 2, 3, 1, 2, 3, ...
* Stream.of(1, 2, 3).cycle();
* </code>
* </pre>
*
* @return A new Stream containing this elements cycled.
*/
default Stream<T> cycle() {
return isEmpty() ? this : appendSelf(Function.identity());
}
/**
* Repeat the elements of this Stream {@code count} times.
* <p>
* Example:
* <pre>
* <code>
* // = empty
* Stream.of(1, 2, 3).cycle(0);
*
* // = 1, 2, 3
* Stream.of(1, 2, 3).cycle(1);
*
* // = 1, 2, 3, 1, 2, 3, 1, 2, 3
* Stream.of(1, 2, 3).cycle(3);
* </code>
* </pre>
*
* @param count the number of cycles to be performed
* @return A new Stream containing this elements cycled {@code count} times.
*/
default Stream<T> cycle(int count) {
if (count <= 0 || isEmpty()) {
return empty();
} else {
final Stream<T> self = this;
return Stream.ofAll(new Iterator<T>() {
Stream<T> stream = self;
int i = count - 1;
@Override
public boolean hasNext() {
return !stream.isEmpty() || i > 0;
}
@Override
public T next() {
if (stream.isEmpty()) {
i--;
stream = self;
}
final T result = stream.head();
stream = stream.tail();
return result;
}
});
}
}
@Override
default Stream<T> distinct() {
return distinctBy(Function.identity());
}
@Override
default Stream<T> distinctBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator, "comparator is null");
final java.util.Set<T> seen = new java.util.TreeSet<>(comparator);
return filter(seen::add);
}
@Override
default <U> Stream<T> distinctBy(Function<? super T, ? extends U> keyExtractor) {
final java.util.Set<U> seen = new java.util.HashSet<>();
return filter(t -> seen.add(keyExtractor.apply(t)));
}
@Override
default Stream<T> drop(int n) {
Stream<T> stream = this;
while (n-- > 0 && !stream.isEmpty()) {
stream = stream.tail();
}
return stream;
}
@Override
default Stream<T> dropUntil(Predicate<? super T> predicate) {
return io.vavr.collection.Collections.dropUntil(this, predicate);
}
@Override
default Stream<T> dropWhile(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return dropUntil(predicate.negate());
}
@Override
default Stream<T> dropRight(int n) {
if (n <= 0) {
return this;
} else {
return DropRight.apply(take(n).toList(), io.vavr.collection.List.empty(), drop(n));
}
}
@Override
default Stream<T> dropRightUntil(Predicate<? super T> predicate) {
return io.vavr.collection.Collections.dropUntil(reverse(), predicate).reverse();
}
@Override
default Stream<T> dropRightWhile(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return dropRightUntil(predicate.negate());
}
@Override
default Stream<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
if (isEmpty()) {
return this;
} else {
Stream<T> stream = this;
while (!stream.isEmpty() && !predicate.test(stream.head())) {
stream = stream.tail();
}
final Stream<T> finalStream = stream;
return stream.isEmpty() ? Stream.empty()
: cons(stream.head(), () -> finalStream.tail().filter(predicate));
}
}
@Override
default <U> Stream<U> flatMap(Function<? super T, ? extends Iterable<? extends U>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return isEmpty() ? Empty.instance() : Stream.ofAll(new Iterator<U>() {
final Iterator<? extends T> inputs = Stream.this.iterator();
java.util.Iterator<? extends U> current = java.util.Collections.emptyIterator();
@Override
public boolean hasNext() {
boolean currentHasNext;
while (!(currentHasNext = current.hasNext()) && inputs.hasNext()) {
current = mapper.apply(inputs.next()).iterator();
}
return currentHasNext;
}
@Override
public U next() {
return current.next();
}
});
}
@Override
default T get(int index) {
if (isEmpty()) {
throw new IndexOutOfBoundsException("get(" + index + ") on Nil");
}
if (index < 0) {
throw new IndexOutOfBoundsException("get(" + index + ")");
}
Stream<T> stream = this;
for (int i = index - 1; i >= 0; i--) {
stream = stream.tail();
if (stream.isEmpty()) {
throw new IndexOutOfBoundsException("get(" + index + ") on Stream of size " + (index - i));
}
}
return stream.head();
}
@Override
default <C> Map<C, Stream<T>> groupBy(Function<? super T, ? extends C> classifier) {
return io.vavr.collection.Collections.groupBy(this, classifier, Stream::ofAll);
}
@Override
default Iterator<Stream<T>> grouped(int size) {
return sliding(size, size);
}
@Override
default boolean hasDefiniteSize() {
return false;
}
@Override
default int indexOf(T element, int from) {
int index = 0;
for (Stream<T> stream = this; !stream.isEmpty(); stream = stream.tail(), index++) {
if (index >= from && Objects.equals(stream.head(), element)) {
return index;
}
}
return -1;
}
@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 Option<Stream<T>> initOption() {
return isEmpty() ? Option.none() : Option.some(init());
}
@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> 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> intersperse(T element) {
if (isEmpty()) {
return this;
} else {
return cons(head(), () -> {
final Stream<T> tail = tail();
return tail.isEmpty() ? tail : cons(element, () -> tail.intersperse(element));
});
}
}
/**
* A {@code Stream} is computed synchronously.
*
* @return false
*/
@Override
default boolean isAsync() {
return false;
}
/**
* A {@code Stream} is computed lazily.
*
* @return true
*/
@Override
default boolean isLazy() {
return true;
}
@Override
default boolean isTraversableAgain() {
return true;
}
@Override
default int lastIndexOf(T element, int end) {
int result = -1, index = 0;
for (Stream<T> stream = this; index <= end && !stream.isEmpty(); stream = stream.tail(), index++) {
if (Objects.equals(stream.head(), element)) {
result = index;
}
}
return result;
}
@Override
default int length() {
return foldLeft(0, (n, ignored) -> n + 1);
}
@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> 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));
}
}
@Override
default Stream<T> leftPadTo(int length, T element) {
final int actualLength = length();
if (length <= actualLength) {
return this;
} else {
return Stream.continually(element).take(length - actualLength).appendAll(this);
}
}
@Override
default Stream<T> orElse(Iterable<? extends T> other) {
return isEmpty() ? ofAll(other) : this;
}
@Override
default Stream<T> orElse(Supplier<? extends Iterable<? extends T>> supplier) {
return isEmpty() ? ofAll(supplier.get()) : this;
}
@Override
default Stream<T> patch(int from, Iterable<? extends T> that, int replaced) {
from = from < 0 ? 0 : from;
replaced = replaced < 0 ? 0 : replaced;
Stream<T> result = take(from).appendAll(that);
from += replaced;
result = result.appendAll(drop(from));
return result;
}
@Override
default Tuple2<Stream<T>, Stream<T>> partition(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return Tuple.of(filter(predicate), filter(predicate.negate()));
}
@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<Stream<T>> permutations() {
if (isEmpty()) {
return Empty.instance();
} else {
final Stream<T> tail = tail();
if (tail.isEmpty()) {
return Stream.of(this);
} else {
final Stream<Stream<T>> zero = Empty.instance();
return distinct().foldLeft(zero, (xs, x) -> {
final Function<Stream<T>, Stream<T>> prepend = l -> l.prepend(x);
return xs.appendAll(remove(x).permutations().map(prepend));
});
}
}
}
@Override
default Stream<T> prepend(T element) {
return cons(element, () -> this);
}
@Override
default Stream<T> prependAll(Iterable<? extends T> elements) {
Objects.requireNonNull(elements, "elements is null");
if (isEmpty()) {
if (elements instanceof Stream) {
@SuppressWarnings("unchecked")
final Stream<T> stream = (Stream<T>) elements;
return stream;
} else {
return Stream.ofAll(elements);
}
} else {
return Stream.<T> ofAll(elements).appendAll(this);
}
}
@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> 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 Stream<T> removeLast(Predicate<T> predicate) {
return isEmpty() ? this : reverse().removeFirst(predicate).reverse();
}
@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> removeAll(T element) {
return io.vavr.collection.Collections.removeAll(this, element);
}
@Override
default Stream<T> removeAll(Iterable<? extends T> elements) {
return io.vavr.collection.Collections.removeAll(this, elements);
}
@Override
default Stream<T> removeAll(Predicate<? super T> predicate) {
return io.vavr.collection.Collections.removeAll(this, predicate);
}
@Override
default Stream<T> replace(T currentElement, T newElement) {
if (isEmpty()) {
return this;
} else {
final T head = head();
if (Objects.equals(head, currentElement)) {
return cons(newElement, this::tail);
} else {
return cons(head, () -> tail().replace(currentElement, newElement));
}
}
}
@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));
}
}
@Override
default Stream<T> retainAll(Iterable<? extends T> elements) {
return io.vavr.collection.Collections.retainAll(this, elements);
}
@Override
default Stream<T> reverse() {
return isEmpty() ? this : foldLeft(Stream.empty(), Stream::prepend);
}
@Override
default Stream<T> scan(T zero, BiFunction<? super T, ? super T, ? extends T> operation) {
return scanLeft(zero, operation);
}
@Override
default <U> Stream<U> scanLeft(U zero, BiFunction<? super U, ? super T, ? extends U> operation) {
// lazily streams the elements of an iterator
return io.vavr.collection.Collections.scanLeft(this, zero, operation, Iterator::toStream);
}
// not lazy!
@Override
default <U> Stream<U> scanRight(U zero, BiFunction<? super T, ? super U, ? extends U> operation) {
return io.vavr.collection.Collections.scanRight(this, zero, operation, Iterator::toStream);
}
@Override
default Stream<T> shuffle() {
return io.vavr.collection.Collections.shuffle(this, Stream::ofAll);
}
@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 Iterator<Stream<T>> slideBy(Function<? super T, ?> classifier) {
return iterator().slideBy(classifier).map(Stream::ofAll);
}
@Override
default Iterator<Stream<T>> sliding(int size) {
return sliding(size, 1);
}
@Override
default Iterator<Stream<T>> sliding(int size, int step) {
return iterator().sliding(size, step).map(Stream::ofAll);
}
@Override
default Stream<T> sorted() {
return isEmpty() ? this : toJavaStream().sorted().collect(Stream.collector());
}
@Override
default Stream<T> sorted(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator, "comparator is null");
return isEmpty() ? this : toJavaStream().sorted(comparator).collect(Stream.collector());
}
@Override
default <U extends Comparable<? super U>> Stream<T> sortBy(Function<? super T, ? extends U> mapper) {
return sortBy(U::compareTo, mapper);
}
@Override
default <U> Stream<T> sortBy(Comparator<? super U> comparator, Function<? super T, ? extends U> mapper) {
final Function<? super T, ? extends U> domain = Function1.of(mapper::apply).memoized();
return toJavaStream()
.sorted((e1, e2) -> comparator.compare(domain.apply(e1), domain.apply(e2)))
.collect(collector());
}
@Override
default Tuple2<Stream<T>, Stream<T>> span(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return Tuple.of(takeWhile(predicate), dropWhile(predicate));
}
@Override
default Tuple2<Stream<T>, Stream<T>> splitAt(int n) {
return Tuple.of(take(n), drop(n));
}
@Override
default Tuple2<Stream<T>, Stream<T>> splitAt(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return Tuple.of(takeWhile(predicate.negate()), dropWhile(predicate.negate()));
}
@Override
default Tuple2<Stream<T>, Stream<T>> splitAtInclusive(Predicate<? super T> predicate) {
final Tuple2<Stream<T>, Stream<T>> split = splitAt(predicate);
if (split._2.isEmpty()) {
return split;
} else {
return Tuple.of(split._1.append(split._2.head()), split._2.tail());
}
}
@Override
default String stringPrefix() {
return "Stream";
}
@Override
default Stream<T> subSequence(int beginIndex) {
if (beginIndex < 0) {
throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ")");
}
Stream<T> result = this;
for (int i = 0; i < beginIndex; i++, result = result.tail()) {
if (result.isEmpty()) {
throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ") on Stream of size " + i);
}
}
return result;
}
@Override
default Stream<T> subSequence(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new IndexOutOfBoundsException("subSequence(" + beginIndex + ", " + endIndex + ")");
}
if (beginIndex > endIndex) {
throw new IllegalArgumentException("subSequence(" + beginIndex + ", " + endIndex + ")");
}
if (beginIndex == endIndex) {
return Empty.instance();
} else if (isEmpty()) {
throw new IndexOutOfBoundsException("subSequence of Nil");
} else if (beginIndex == 0) {
return cons(head(), () -> tail().subSequence(0, endIndex - 1));
} else {
return tail().subSequence(beginIndex - 1, endIndex - 1);
}
}
@Override
Stream<T> tail();
@Override
default Option<Stream<T>> tailOption() {
return isEmpty() ? Option.none() : Option.some(tail());
}
@Override
default Stream<T> take(int n) {
if (n < 1 || isEmpty()) {
return empty();
} else if (n == 1) {
return cons(head(), Stream::empty);
} else {
return cons(head(), () -> tail().take(n - 1));
}
}
@Override
default Stream<T> takeRight(int n) {
Stream<T> right = this;
Stream<T> remaining = drop(n);
while (!remaining.isEmpty()) {
right = right.tail();
remaining = remaining.tail();
}
return right;
}
@Override
default Stream<T> takeUntil(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return takeWhile(predicate.negate());
}
@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();
}
}
}
/**
* Transforms this {@code Stream}.
*
* @param f A transformation
* @param <U> Type of transformation result
* @return An instance of type {@code U}
* @throws NullPointerException if {@code f} is null
*/
default <U> U transform(Function<? super Stream<T>, ? extends U> f) {
Objects.requireNonNull(f, "f is null");
return f.apply(this);
}
@Override
default <T1, T2> Tuple2<Stream<T1>, Stream<T2>> unzip(
Function<? super T, Tuple2<? extends T1, ? extends T2>> unzipper) {
Objects.requireNonNull(unzipper, "unzipper is null");
final Stream<Tuple2<? extends T1, ? extends T2>> stream = map(unzipper);
final Stream<T1> stream1 = stream.map(t -> t._1);
final Stream<T2> stream2 = stream.map(t -> t._2);
return Tuple.of(stream1, stream2);
}
@Override
default <T1, T2, T3> Tuple3<Stream<T1>, Stream<T2>, Stream<T3>> unzip3(
Function<? super T, Tuple3<? extends T1, ? extends T2, ? extends T3>> unzipper) {
Objects.requireNonNull(unzipper, "unzipper is null");
final Stream<Tuple3<? extends T1, ? extends T2, ? extends T3>> stream = map(unzipper);
final Stream<T1> stream1 = stream.map(t -> t._1);
final Stream<T2> stream2 = stream.map(t -> t._2);
final Stream<T3> stream3 = stream.map(t -> t._3);
return Tuple.of(stream1, stream2, stream3);
}
@Override
default Stream<T> update(int index, T element) {
if (isEmpty()) {
throw new IndexOutOfBoundsException("update(" + index + ", e) on Nil");
}
if (index < 0) {
throw new IndexOutOfBoundsException("update(" + index + ", e)");
}
Stream<T> preceding = Empty.instance();
Stream<T> tail = this;
for (int i = index; i > 0; i--, tail = tail.tail()) {
if (tail.isEmpty()) {
throw new IndexOutOfBoundsException("update at " + index);
}
preceding = preceding.prepend(tail.head());
}
if (tail.isEmpty()) {
throw new IndexOutOfBoundsException("update at " + index);
}
// skip the current head element because it is replaced
return preceding.reverse().appendAll(tail.tail().prepend(element));
}
@Override
default Stream<T> update(int index, Function<? super T, ? extends T> updater) {
Objects.requireNonNull(updater, "updater is null");
return update(index, updater.apply(get(index)));
}
@Override
default <U> Stream<Tuple2<T, U>> zip(Iterable<? extends U> that) {
return zipWith(that, Tuple::of);
}
@Override
default <U, R> Stream<R> zipWith(Iterable<? extends U> that, BiFunction<? super T, ? super U, ? extends R> mapper) {
Objects.requireNonNull(that, "that is null");
Objects.requireNonNull(mapper, "mapper is null");
return Stream.ofAll(iterator().zipWith(that, mapper));
}
@Override
default <U> Stream<Tuple2<T, U>> zipAll(Iterable<? extends U> iterable, T thisElem, U thatElem) {
Objects.requireNonNull(iterable, "iterable is null");
return Stream.ofAll(iterator().zipAll(iterable, thisElem, thatElem));
}
@Override
default Stream<Tuple2<T, Integer>> zipWithIndex() {
return zipWithIndex(Tuple::of);
}
@Override
default <U> Stream<U> zipWithIndex(BiFunction<? super T, ? super Integer, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return Stream.ofAll(iterator().zipWithIndex(mapper));
}
/**
* Extends (continues) this {@code Stream} with a constantly repeated value.
*
* @param next value with which the stream should be extended
* @return new {@code Stream} composed from this stream extended with a Stream of provided value
*/
default Stream<T> extend(T next) {
return Stream.ofAll(this.appendAll(Stream.continually(next)));
}
/**
* Extends (continues) this {@code Stream} with values provided by a {@code Supplier}
*
* @param nextSupplier a supplier which will provide values for extending a stream
* @return new {@code Stream} composed from this stream extended with values provided by the supplier
*/
default Stream<T> extend(Supplier<? extends T> nextSupplier) {
Objects.requireNonNull(nextSupplier, "nextSupplier is null");
return Stream.ofAll(appendAll(Stream.continually(nextSupplier)));
}
/**
* Extends (continues) this {@code Stream} with a Stream of values created by applying
* consecutively provided {@code Function} to the last element of the original Stream.
*
* @param nextFunction a function which calculates the next value basing on the previous value
* @return new {@code Stream} composed from this stream extended with values calculated by the provided function
*/
default Stream<T> extend(Function<? super T, ? extends T> nextFunction) {
Objects.requireNonNull(nextFunction, "nextFunction is null");
if (isEmpty()) {
return this;
} else {
final Stream<T> that = this;
return Stream.ofAll(new AbstractIterator<T>() {
Stream<T> stream = that;
T last = null;
@Override
protected T getNext() {
if (stream.isEmpty()) {
stream = Stream.iterate(nextFunction.apply(last), nextFunction);
}
last = stream.head();
stream = stream.tail();
return last;
}
@Override
public boolean hasNext() {
return true;
}
});
}
}
/**
* The empty Stream.
* <p>
* This is a singleton, i.e. not Cloneable.
*
* @param <T> Component type of the Stream.
*/
final class Empty<T> implements Stream<T>, Serializable {
private static final long serialVersionUID = 1L;
private static final Empty<?> INSTANCE = new Empty<>();
// hidden
private Empty() {
}
/**
* Returns the singleton empty Stream instance.
*
* @param <T> Component type of the Stream
* @return The empty Stream
*/
@SuppressWarnings("unchecked")
public static <T> Empty<T> instance() {
return (Empty<T>) INSTANCE;
}
@Override
public T head() {
throw new NoSuchElementException("head of empty stream");
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public Iterator<T> iterator() {
return Iterator.empty();
}
@Override
public Stream<T> tail() {
throw new UnsupportedOperationException("tail of empty stream");
}
@Override
public boolean equals(Object o) {
return io.vavr.collection.Collections.equals(this, o);
}
@Override
public int hashCode() {
return io.vavr.collection.Collections.hashOrdered(this);
}
@Override
public String toString() {
return stringPrefix() + "()";
}
/**
* Instance control for object serialization.
*
* @return The singleton instance of Nil.
* @see java.io.Serializable
*/
private Object readResolve() {
return INSTANCE;
}
}
/**
* Non-empty {@code Stream}, consisting of a {@code head}, and {@code tail}.
*
* @param <T> Component type of the Stream.
*/
abstract class Cons<T> implements Stream<T> {
private static final long serialVersionUID = 1L;
final T head;
final Lazy<Stream<T>> tail;
Cons(T head, Supplier<Stream<T>> tail) {
Objects.requireNonNull(tail, "tail is null");
this.head = head;
this.tail = Lazy.of(tail);
}
@Override
public T head() {
return head;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Iterator<T> iterator() {
return new StreamIterator<>(this);
}
@Override
public boolean equals(Object o) {
return io.vavr.collection.Collections.equals(this, o);
}
@Override
public int hashCode() {
return io.vavr.collection.Collections.hashOrdered(this);
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder(stringPrefix()).append("(");
Stream<T> stream = this;
while (stream != null && !stream.isEmpty()) {
final Cons<T> cons = (Cons<T>) stream;
builder.append(cons.head);
if (cons.tail.isEvaluated()) {
stream = stream.tail();
if (!stream.isEmpty()) {
builder.append(", ");
}
} else {
builder.append(", ?");
stream = null;
}
}
return builder.append(")").toString();
}
}
}
interface StreamModule {
final class ConsImpl<T> extends Cons<T> implements Serializable {
private static final long serialVersionUID = 1L;
ConsImpl(T head, Supplier<Stream<T>> tail) {
super(head, tail);
}
@Override
public Stream<T> tail() {
return tail.get();
}
@GwtIncompatible("The Java serialization protocol is explicitly not supported")
private Object writeReplace() {
return new SerializationProxy<>(this);
}
@GwtIncompatible("The Java serialization protocol is explicitly not supported")
private void readObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
}
final class AppendElements<T> extends Cons<T> implements Serializable {
private static final long serialVersionUID = 1L;
private final io.vavr.collection.Queue<T> queue;
AppendElements(T head, io.vavr.collection.Queue<T> queue, Supplier<Stream<T>> tail) {
super(head, tail);
this.queue = queue;
}
@Override
public Stream<T> append(T element) {
return new AppendElements<>(head, queue.append(element), tail);
}
@Override
public Stream<T> appendAll(Iterable<? extends T> elements) {
Objects.requireNonNull(elements, "elements is null");
return isEmpty() ? Stream.ofAll(queue) : new AppendElements<>(head, queue.appendAll(elements), tail);
}
@Override
public Stream<T> tail() {
final Stream<T> t = tail.get();
if (t.isEmpty()) {
return Stream.ofAll(queue);
} else {
if (t instanceof ConsImpl) {
final ConsImpl<T> c = (ConsImpl<T>) t;
return new AppendElements<>(c.head(), queue, c.tail);
} else {
final AppendElements<T> a = (AppendElements<T>) t;
return new AppendElements<>(a.head(), a.queue.appendAll(queue), a.tail);
}
}
}
@GwtIncompatible("The Java serialization protocol is explicitly not supported")
private Object writeReplace() {
return new SerializationProxy<>(this);
}
@GwtIncompatible("The Java serialization protocol is explicitly not supported")
private void readObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
}
/**
* A serialization proxy which, in this context, is used to deserialize immutable, linked Streams with final
* instance fields.
*
* @param <T> The component type of the underlying stream.
*/
// DEV NOTE: The serialization proxy pattern is not compatible with non-final, i.e. extendable,
// classes. Also, it may not be compatible with circular object graphs.
@GwtIncompatible("The Java serialization protocol is explicitly not supported")
final class SerializationProxy<T> implements Serializable {
private static final long serialVersionUID = 1L;
// the instance to be serialized/deserialized
private transient Cons<T> stream;
/**
* Constructor for the case of serialization.
* <p>
* The constructor of a SerializationProxy takes an argument that concisely represents the logical state of
* an instance of the enclosing class.
*
* @param stream a Cons
*/
SerializationProxy(Cons<T> stream) {
this.stream = stream;
}
/**
* Write an object to a serialization stream.
*
* @param s An object serialization stream.
* @throws java.io.IOException If an error occurs writing to the stream.
*/
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
s.writeInt(stream.length());
for (Stream<T> l = stream; !l.isEmpty(); l = l.tail()) {
s.writeObject(l.head());
}
}
/**
* Read an object from a deserialization stream.
*
* @param s An object deserialization stream.
* @throws ClassNotFoundException If the object's class read from the stream cannot be found.
* @throws InvalidObjectException If the stream contains no stream elements.
* @throws IOException If an error occurs reading from the stream.
*/
private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
s.defaultReadObject();
final int size = s.readInt();
if (size <= 0) {
throw new InvalidObjectException("No elements");
}
Stream<T> temp = Empty.instance();
for (int i = 0; i < size; i++) {
@SuppressWarnings("unchecked")
final T element = (T) s.readObject();
temp = temp.append(element);
}
// DEV-NOTE: Cons is deserialized
stream = (Cons<T>) temp;
}
/**
* {@code readResolve} method for the serialization proxy pattern.
* <p>
* Returns a logically equivalent instance of the enclosing class. The presence of this method causes the
* serialization system to translate the serialization proxy back into an instance of the enclosing class
* upon deserialization.
*
* @return A deserialized instance of the enclosing class.
*/
private Object readResolve() {
return stream;
}
}
final class AppendSelf<T> {
private final Cons<T> self;
AppendSelf(Cons<T> self, Function<? super Stream<T>, ? extends Stream<T>> mapper) {
this.self = appendAll(self, mapper);
}
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);
});
}
Cons<T> stream() {
return self;
}
}
interface Combinations {
static <T> Stream<Stream<T>> apply(Stream<T> elements, int k) {
if (k == 0) {
return Stream.of(Stream.empty());
} else {
return elements.zipWithIndex().flatMap(
t -> apply(elements.drop(t._2 + 1), (k - 1)).map((Stream<T> c) -> c.prepend(t._1))
);
}
}
}
interface DropRight {
// works with infinite streams by buffering elements
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()));
}
}
}
interface StreamFactory {
static <T> Stream<T> create(java.util.Iterator<? extends T> iterator) {
return iterator.hasNext() ? Stream.cons(iterator.next(), () -> create(iterator)) : Empty.instance();
}
}
final class StreamIterator<T> extends AbstractIterator<T> {
private Supplier<Stream<T>> current;
StreamIterator(Cons<T> stream) {
this.current = () -> stream;
}
@Override
public boolean hasNext() {
return !current.get().isEmpty();
}
@Override
public T getNext() {
final Stream<T> stream = current.get();
// DEV-NOTE: we make the stream even more lazy because the next head must not be evaluated on hasNext()
current = stream::tail;
return stream.head();
}
}
}