All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jooq.lambda.Seq Maven / Gradle / Ivy

Go to download

jOOλ is part of the jOOQ series (along with jOOQ, jOOX, jOOR, jOOU) providing some useful extensions to Java 8 lambdas.

There is a newer version: 0.9.15
Show newest version
/**
 * Copyright (c) 2014, Data Geekery GmbH, [email protected]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jooq.lambda;
import static java.util.Comparator.comparing;
import static java.util.Comparator.naturalOrder;
import static java.util.Spliterator.ORDERED;
import static java.util.Spliterators.spliteratorUnknownSize;
import static org.jooq.lambda.tuple.Tuple.tuple;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.jooq.lambda.tuple.Tuple;
import org.jooq.lambda.tuple.Tuple2;


/**
 * A sequential, ordered {@link Stream} that adds all sorts of useful methods that work only because
 * it is sequential and ordered.
 *
 * @author Lukas Eder
 */
public interface Seq extends Stream, Iterable {

    /**
     * The underlying {@link Stream} implementation.
     */
    Stream stream();

    /**
     * Concatenate two streams.
     * 

*

     * // (1, 2, 3, 4, 5, 6)
     * Seq.of(1, 2, 3).concat(Seq.of(4, 5, 6))
     * 
* * @see #concat(Stream[]) */ default Seq concat(Stream other) { return Seq.concat(new Stream[]{this, other}); } /** * Repeat a stream infinitely. *

*

     * // (1, 2, 3, 1, 2, 3, ...)
     * Seq.of(1, 2, 3).cycle();
     * 
* * @see #cycle(Stream) */ default Seq cycle() { return cycle(this); } /** * Zip two streams into one. *

*

     * // (tuple(1, "a"), tuple(2, "b"), tuple(3, "c"))
     * Seq.of(1, 2, 3).zip(Seq.of("a", "b", "c"))
     * 
* * @see #zip(Stream, Stream) */ default Seq> zip(Seq other) { return zip(this, other); } /** * Zip two streams into one using a {@link BiFunction} to produce resulting values. *

*

     * // ("1:a", "2:b", "3:c")
     * Seq.of(1, 2, 3).zip(Seq.of("a", "b", "c"), (i, s) -> i + ":" + s)
     * 
* * @see #zip(Seq, BiFunction) */ default Seq zip(Seq other, BiFunction zipper) { return zip(this, other, zipper); } /** * Zip a Stream with a corresponding Stream of indexes. *

*

     * // (tuple("a", 0), tuple("b", 1), tuple("c", 2))
     * Seq.of("a", "b", "c").zipWithIndex()
     * 
* * @see #zipWithIndex(Stream) */ default Seq> zipWithIndex() { return zipWithIndex(this); } /** * Fold a Stream to the left. *

*

     * // "abc"
     * Seq.of("a", "b", "c").foldLeft("", (u, t) -> u + t)
     * 
*/ default U foldLeft(U seed, BiFunction function) { return foldLeft(this, seed, function); } /** * Fold a Stream to the right. *

*

     * // "cba"
     * Seq.of("a", "b", "c").foldRight("", (t, u) -> u + t)
     * 
*/ default U foldRight(U seed, BiFunction function) { return foldRight(this, seed, function); } /** * Reverse a stream. *

*

     * // (3, 2, 1)
     * Seq.of(1, 2, 3).reverse()
     * 
*/ default Seq reverse() { return reverse(this); } /** * Returns a stream with all elements skipped for which a predicate evaluates to true. *

*

     * // (3, 4, 5)
     * Seq.of(1, 2, 3, 4, 5).skipWhile(i -> i < 3)
     * 
* * @see #skipWhile(Stream, Predicate) */ default Seq skipWhile(Predicate predicate) { return skipWhile(this, predicate); } /** * Returns a stream with all elements skipped for which a predicate evaluates to false. *

*

     * // (3, 4, 5)
     * Seq.of(1, 2, 3, 4, 5).skipUntil(i -> i == 3)
     * 
* * @see #skipUntil(Stream, Predicate) */ default Seq skipUntil(Predicate predicate) { return skipUntil(this, predicate); } /** * Returns a stream limited to all elements for which a predicate evaluates to true. *

*

     * // (1, 2)
     * Seq.of(1, 2, 3, 4, 5).limitWhile(i -> i < 3)
     * 
* * @see #limitWhile(Stream, Predicate) */ default Seq limitWhile(Predicate predicate) { return limitWhile(this, predicate); } /** * Returns a stream limited to all elements for which a predicate evaluates to false. *

*

     * // (1, 2)
     * Seq.of(1, 2, 3, 4, 5).limitUntil(i -> i == 3)
     * 
* * @see #limitUntil(Stream, Predicate) */ default Seq limitUntil(Predicate predicate) { return limitUntil(this, predicate); } /** * Returns a stream with a given value interspersed between any two values of this stream. *

*

     * // (1, 0, 2, 0, 3, 0, 4)
     * Seq.of(1, 2, 3, 4).intersperse(0)
     * 
* * @see #intersperse(Stream, T) */ default Seq intersperse(T value) { return intersperse(this, value); } /** * Duplicate a Streams into two equivalent Streams. *

*

     * // tuple((1, 2, 3), (1, 2, 3))
     * Seq.of(1, 2, 3).duplicate()
     * 
* * @see #duplicate(Stream) */ default Tuple2, Seq> duplicate() { return duplicate(this); } /** * Partition a stream into two given a predicate. *

*

     * // tuple((1, 3, 5), (2, 4, 6))
     * Seq.of(1, 2, 3, 4, 5, 6).partition(i -> i % 2 != 0)
     * 
* * @see #partition(Stream, Predicate) */ default Tuple2, Seq> partition(Predicate predicate) { return partition(this, predicate); } /** * Split a stream at a given position. *

*

     * // tuple((1, 2, 3), (4, 5, 6))
     * Seq.of(1, 2, 3, 4, 5, 6).splitAt(3)
     * 
* * @see #splitAt(Stream, long) */ default Tuple2, Seq> splitAt(long position) { return splitAt(this, position); } /** * Split a stream at the head. *

*

     * // tuple(1, (2, 3, 4, 5, 6))
     * Seq.of(1, 2, 3, 4, 5, 6).splitHead(3)
     * 
* * @see #splitAt(Stream, long) */ default Tuple2, Seq> splitAtHead() { return splitAtHead(this); } /** * Returns a limited interval from a given Stream. *

*

     * // (4, 5)
     * Seq.of(1, 2, 3, 4, 5, 6).slice(3, 5)
     * 
* * @see #slice(Stream, long, long) */ default Seq slice(long from, long to) { return slice(this, from, to); } /** * Collect a Stream into a Collection. * * @see #toCollection(Stream, Supplier) */ default > C toCollection(Supplier collectionFactory) { return toCollection(this, collectionFactory); } /** * Collect a Stream into a List. * * @see #toList(Stream) */ default List toList() { return toList(this); } /** * Collect a Stream into a Set. * * @see #toSet(Stream) */ default Set toSet() { return toSet(this); } /** * Collect a Stream into a Map. * * @see #toMap(Stream, Function, Function) */ default Map toMap(Function keyMapper, Function valueMapper) { return toMap(this, keyMapper, valueMapper); } /** * Consume a stream and concatenate all elements using a separator. */ default String toString(String separator) { return toString(this, separator); } /** * Get the maximum value by a function. */ default > Optional minBy(Function function) { return minBy(function, naturalOrder()); } /** * Get the maximum value by a function. */ default Optional minBy(Function function, Comparator comparator) { return map(t -> tuple(t, function.apply(t))) .min(comparing(Tuple2::v2, comparator)) .map(t -> t.v1); } /** * Get the maximum value by a function. */ default > Optional maxBy(Function function) { return maxBy(function, naturalOrder()); } /** * Get the maximum value by a function. */ default Optional maxBy(Function function, Comparator comparator) { return map(t -> tuple(t, function.apply(t))) .max(comparing(Tuple2::v2, comparator)) .map(t -> t.v1); } // Methods taken from LINQ // ----------------------- /** * Keep only those elements in a stream that are of a given type. *

*

     * // (1, 2, 3)
     * Seq.of(1, "a", 2, "b", 3).ofType(Integer.class)
     * 
* * @see #ofType(Stream, Class) */ default Seq ofType(Class type) { return ofType(this, type); } /** * Cast all elements in a stream to a given type, possibly throwing a {@link ClassCastException}. *

*

     * // ClassCastException
     * Seq.of(1, "a", 2, "b", 3).cast(Integer.class)
     * 
* * @see #cast(Stream, Class) */ default Seq cast(Class type) { return cast(this, type); } /** * @see Stream#of(Object) */ static Seq of(T value) { return seq(Stream.of(value)); } /** * @see Stream#of(Object[]) */ static Seq of(T... values) { return seq(Stream.of(values)); } /** * @see Stream#empty() */ static Seq empty() { return seq(Stream.empty()); } /** * @see Stream#iterate(Object, UnaryOperator) */ static Seq iterate(final T seed, final UnaryOperator f) { return seq(Stream.iterate(seed, f)); } /** * @see Stream#generate(Supplier) */ static Seq generate() { return generate(() -> null); } /** * @see Stream#generate(Supplier) */ static Seq generate(T value) { return generate(() -> value); } /** * @see Stream#generate(Supplier) */ static Seq generate(Supplier s) { return seq(Stream.generate(s)); } /** * Wrap a Stream into a Seq. */ static Seq seq(Stream stream) { if (stream instanceof Seq) return (Seq) stream; return new SeqImpl<>(stream); } /** * Wrap an Iterable into a Seq. */ static Seq seq(Iterable iterable) { return seq(iterable.iterator()); } /** * Wrap an Iterator into a Seq. */ static Seq seq(Iterator iterator) { return seq(StreamSupport.stream(spliteratorUnknownSize(iterator, ORDERED), false)); } /** * Wrap a Map into a Seq. */ static Seq> seq(Map map) { return seq(map.entrySet()).map(e -> tuple(e.getKey(), e.getValue())); } /** * Repeat a stream infinitely. *

*

     * // (1, 2, 3, 1, 2, 3, ...)
     * Seq.of(1, 2, 3).cycle();
     * 
*/ static Seq cycle(Stream stream) { final List list = new ArrayList(); class Cycle implements Iterator { boolean cycled; Iterator it; Cycle(Iterator it) { this.it = it; } @Override public boolean hasNext() { return true; } @Override public T next() { if (!it.hasNext()) { cycled = true; it = list.iterator(); } T next = it.next(); if (!cycled) { list.add(next); } return next; } } return seq(new Cycle(stream.iterator())); } /** * Unzip one Stream into two. *

*

     * // tuple((1, 2, 3), (a, b, c))
     * Seq.unzip(Seq.of(tuple(1, "a"), tuple(2, "b"), tuple(3, "c")));
     * 
*/ static Tuple2, Seq> unzip(Stream> stream) { return unzip(stream, t -> t); } /** * Unzip one Stream into two. *

*

     * // tuple((1, 2, 3), (a, b, c))
     * Seq.unzip(Seq.of(tuple(1, "a"), tuple(2, "b"), tuple(3, "c")));
     * 
*/ static Tuple2, Seq> unzip(Stream> stream, Function leftUnzipper, Function rightUnzipper) { return unzip(stream, t -> tuple(leftUnzipper.apply(t.v1), rightUnzipper.apply(t.v2))); } /** * Unzip one Stream into two. *

*

     * // tuple((1, 2, 3), (a, b, c))
     * Seq.unzip(Seq.of(tuple(1, "a"), tuple(2, "b"), tuple(3, "c")));
     * 
*/ static Tuple2, Seq> unzip(Stream> stream, Function, Tuple2> unzipper) { return unzip(stream, (t1, t2) -> unzipper.apply(tuple(t1, t2))); } /** * Unzip one Stream into two. *

*

     * // tuple((1, 2, 3), (a, b, c))
     * Seq.unzip(Seq.of(tuple(1, "a"), tuple(2, "b"), tuple(3, "c")));
     * 
*/ static Tuple2, Seq> unzip(Stream> stream, BiFunction> unzipper) { return seq(stream) .map(t -> unzipper.apply(t.v1, t.v2)) .duplicate() .map1(s -> s.map(u -> u.v1)) .map2(s -> s.map(u -> u.v2)); } /** * Zip two streams into one. *

*

     * // (tuple(1, "a"), tuple(2, "b"), tuple(3, "c"))
     * Seq.of(1, 2, 3).zip(Seq.of("a", "b", "c"))
     * 
*/ static Seq> zip(Stream left, Stream right) { return zip(left, right, Tuple::tuple); } /** * Zip two streams into one using a {@link BiFunction} to produce resulting values. *

*

     * // ("1:a", "2:b", "3:c")
     * Seq.of(1, 2, 3).zip(Seq.of("a", "b", "c"), (i, s) -> i + ":" + s)
     * 
*/ static Seq zip(Stream left, Stream right, BiFunction zipper) { final Iterator it1 = left.iterator(); final Iterator it2 = right.iterator(); class Zip implements Iterator { @Override public boolean hasNext() { return it1.hasNext() && it2.hasNext(); } @Override public R next() { return zipper.apply(it1.next(), it2.next()); } } return seq(new Zip()); } /** * Zip a Stream with a corresponding Stream of indexes. *

*

     * // (tuple("a", 0), tuple("b", 1), tuple("c", 2))
     * Seq.of("a", "b", "c").zipWithIndex()
     * 
*/ static Seq> zipWithIndex(Stream stream) { final Iterator it = stream.iterator(); class ZipWithIndex implements Iterator> { long index; @Override public boolean hasNext() { return it.hasNext(); } @Override public Tuple2 next() { return tuple(it.next(), index++); } } return seq(new ZipWithIndex()); } /** * Fold a stream to the left. *

*

     * // "abc"
     * Seq.of("a", "b", "c").foldLeft("", (u, t) -> u + t)
     * 
*/ static U foldLeft(Stream stream, U seed, BiFunction function) { final Iterator it = stream.iterator(); U result = seed; while (it.hasNext()) result = function.apply(result, it.next()); return result; } /** * Fold a stream to the right. *

*

     * // "cba"
     * Seq.of("a", "b", "c").foldRight("", (t, u) -> u + t)
     * 
*/ static U foldRight(Stream stream, U seed, BiFunction function) { return seq(stream).reverse().foldLeft(seed, (u, t) -> function.apply(t, u)); } /** * Unfold a function into a stream. *

*

     * // (1, 2, 3, 4, 5)
     * Seq.unfold(1, i -> i <= 6 ? Optional.of(tuple(i, i + 1)) : Optional.empty())
     * 
*/ static Seq unfold(U seed, Function>> unfolder) { class Unfold implements Iterator { U u; Optional> unfolded; public Unfold(U u) { this.u = u; } void unfold() { if (unfolded == null) unfolded = unfolder.apply(u); } @Override public boolean hasNext() { unfold(); return unfolded.isPresent(); } @Override public T next() { unfold(); try { return unfolded.get().v1; } finally { u = unfolded.get().v2; unfolded = null; } } } return seq(new Unfold(seed)); } /** * Reverse a stream. *

*

     * // (3, 2, 1)
     * Seq.of(1, 2, 3).reverse()
     * 
*/ static Seq reverse(Stream stream) { List list = toList(stream); Collections.reverse(list); return seq(list); } /** * Concatenate a number of streams. *

*

     * // (1, 2, 3, 4, 5, 6)
     * Seq.of(1, 2, 3).concat(Seq.of(4, 5, 6))
     * 
*/ @SafeVarargs static Seq concat(Stream... streams) { if (streams == null || streams.length == 0) return Seq.empty(); if (streams.length == 1) return seq(streams[0]); Stream result = streams[0]; for (int i = 1; i < streams.length; i++) result = Stream.concat(result, streams[i]); return seq(result); } /** * Duplicate a Streams into two equivalent Streams. *

*

     * // tuple((1, 2, 3), (1, 2, 3))
     * Seq.of(1, 2, 3).duplicate()
     * 
*/ static Tuple2, Seq> duplicate(Stream stream) { final LinkedList gap = new LinkedList<>(); final Iterator it = stream.iterator(); @SuppressWarnings("unchecked") final Iterator[] ahead = new Iterator[] { null }; class Duplicate implements Iterator { @Override public boolean hasNext() { if (ahead[0] == null || ahead[0] == this) return it.hasNext(); return !gap.isEmpty(); } @Override public T next() { if (ahead[0] == null) ahead[0] = this; if (ahead[0] == this) { T value = it.next(); gap.offer(value); return value; } return gap.poll(); } } return tuple(seq(new Duplicate()), seq(new Duplicate())); } /** * Consume a stream and concatenate all elements. */ static String toString(Stream stream) { return toString(stream, ""); } /** * Consume a stream and concatenate all elements using a separator. */ static String toString(Stream stream, String separator) { return stream.map(Objects::toString).collect(Collectors.joining(separator)); } /** * Collect a Stream into a List. */ static > C toCollection(Stream stream, Supplier collectionFactory) { return stream.collect(Collectors.toCollection(collectionFactory)); } /** * Collect a Stream into a List. */ static List toList(Stream stream) { return stream.collect(Collectors.toList()); } /** * Collect a Stream into a Set. */ static Set toSet(Stream stream) { return stream.collect(Collectors.toSet()); } /** * Collect a Stream into a Map. */ static Map toMap(Stream stream, Function keyMapper, Function valueMapper) { return stream.collect(Collectors.toMap(keyMapper, valueMapper)); } /** * Returns a limited interval from a given Stream. *

*

     * // (4, 5)
     * Seq.of(1, 2, 3, 4, 5, 6).slice(3, 5)
     * 
*/ static Seq slice(Stream stream, long from, long to) { long f = Math.max(from, 0); long t = Math.max(to - f, 0); return seq(stream.skip(f).limit(t)); } /** * Returns a stream with n elements skipped. *

*

     * // (4, 5, 6)
     * Seq.of(1, 2, 3, 4, 5, 6).skip(3)
     * 
*/ static Seq skip(Stream stream, long elements) { return seq(stream.skip(elements)); } /** * Returns a stream with all elements skipped for which a predicate evaluates to true. *

*

     * // (3, 4, 5)
     * Seq.of(1, 2, 3, 4, 5).skipWhile(i -> i < 3)
     * 
*/ static Seq skipWhile(Stream stream, Predicate predicate) { return skipUntil(stream, predicate.negate()); } /** * Returns a stream with all elements skipped for which a predicate evaluates to false. *

*

     * // (3, 4, 5)
     * Seq.of(1, 2, 3, 4, 5).skipUntil(i -> i == 3)
     * 
*/ static Seq skipUntil(Stream stream, Predicate predicate) { final Iterator it = stream.iterator(); class SkipUntil implements Iterator { T next = (T) SeqImpl.NULL; boolean test = false; void skip() { while (next == SeqImpl.NULL && it.hasNext()) { next = it.next(); if (test || (test = predicate.test(next))) break; else next = (T) SeqImpl.NULL; } } @Override public boolean hasNext() { skip(); return next != SeqImpl.NULL; } @Override public T next() { if (next == SeqImpl.NULL) throw new NoSuchElementException(); try { return next; } finally { next = (T) SeqImpl.NULL; } } } return seq(new SkipUntil()); } /** * Returns a stream limited to n elements. *

*

     * // (1, 2, 3)
     * Seq.of(1, 2, 3, 4, 5, 6).limit(3)
     * 
*/ static Seq limit(Stream stream, long elements) { return seq(stream.limit(elements)); } /** * Returns a stream limited to all elements for which a predicate evaluates to true. *

*

     * // (1, 2)
     * Seq.of(1, 2, 3, 4, 5).limitWhile(i -> i < 3)
     * 
*/ static Seq limitWhile(Stream stream, Predicate predicate) { return limitUntil(stream, predicate.negate()); } /** * Returns a stream limited to all elements for which a predicate evaluates to true. *

*

     * // (1, 2)
     * Seq.of(1, 2, 3, 4, 5).limitUntil(i -> i == 3)
     * 
*/ static Seq limitUntil(Stream stream, Predicate predicate) { final Iterator it = stream.iterator(); class LimitUntil implements Iterator { T next = (T) SeqImpl.NULL; boolean test = false; void test() { if (!test && next == SeqImpl.NULL && it.hasNext()) { next = it.next(); if (test = predicate.test(next)) next = (T) SeqImpl.NULL; } } @Override public boolean hasNext() { test(); return next != SeqImpl.NULL; } @Override public T next() { if (next == SeqImpl.NULL) throw new NoSuchElementException(); try { return next; } finally { next = (T) SeqImpl.NULL; } } } return seq(new LimitUntil()); } /** * Returns a stream with a given value interspersed between any two values of this stream. *

*

     * // (1, 0, 2, 0, 3, 0, 4)
     * Seq.of(1, 2, 3, 4).intersperse(0)
     * 
*/ static Seq intersperse(Stream stream, T value) { return seq(stream.flatMap(t -> Stream.of(value, t)).skip(1)); } /** * Partition a stream into two given a predicate. *

*

     * // tuple((1, 3, 5), (2, 4, 6))
     * Seq.of(1, 2, 3, 4, 5, 6).partition(i -> i % 2 != 0)
     * 
*/ static Tuple2, Seq> partition(Stream stream, Predicate predicate) { final Iterator it = stream.iterator(); final LinkedList buffer1 = new LinkedList<>(); final LinkedList buffer2 = new LinkedList<>(); class Partition implements Iterator { final boolean b; Partition(boolean b) { this.b = b; } void fetch() { while (buffer(b).isEmpty() && it.hasNext()) { T next = it.next(); buffer(predicate.test(next)).offer(next); } } LinkedList buffer(boolean test) { return test ? buffer1 : buffer2; } @Override public boolean hasNext() { fetch(); return !buffer(b).isEmpty(); } @Override public T next() { return buffer(b).poll(); } } return tuple(seq(new Partition(true)), seq(new Partition(false))); } /** * Split a stream at a given position. *

*

     * // tuple((1, 2, 3), (4, 5, 6))
     * Seq.of(1, 2, 3, 4, 5, 6).splitAt(3)
     * 
*/ static Tuple2, Seq> splitAt(Stream stream, long position) { return seq(stream) .zipWithIndex() .partition(t -> t.v2 < position) .map((v1, v2) -> tuple( v1.map(t -> t.v1), v2.map(t -> t.v1) )); } /** * Split a stream at the head. *

*

     * // tuple(1, (2, 3, 4, 5, 6))
     * Seq.of(1, 2, 3, 4, 5, 6).splitHead(3)
     * 
*/ static Tuple2, Seq> splitAtHead(Stream stream) { Iterator it = stream.iterator(); return tuple(it.hasNext() ? Optional.of(it.next()) : Optional.empty(), seq(it)); } // Methods taken from LINQ // ----------------------- /** * Keep only those elements in a stream that are of a given type. *

*

     * // (1, 2, 3)
     * Seq.of(1, "a", 2, "b", 3).ofType(Integer.class)
     * 
*/ static Seq ofType(Stream stream, Class type) { return seq(stream).filter(t -> type.isInstance(t)).map(t -> (U) t); } /** * Cast all elements in a stream to a given type, possibly throwing a {@link ClassCastException}. *

*

     * // ClassCastException
     * Seq.of(1, "a", 2, "b", 3).cast(Integer.class)
     * 
*/ static Seq cast(Stream stream, Class type) { return seq(stream).map(t -> type.cast(t)); } // Covariant overriding of Stream return types // ------------------------------------------- @Override Seq filter(Predicate predicate); @Override Seq map(Function mapper); @Override IntStream mapToInt(ToIntFunction mapper); @Override LongStream mapToLong(ToLongFunction mapper); @Override DoubleStream mapToDouble(ToDoubleFunction mapper); @Override Seq flatMap(Function> mapper); @Override IntStream flatMapToInt(Function mapper); @Override LongStream flatMapToLong(Function mapper); @Override DoubleStream flatMapToDouble(Function mapper); @Override Seq distinct(); @Override Seq sorted(); @Override Seq sorted(Comparator comparator); @Override Seq peek(Consumer action); @Override Seq limit(long maxSize); @Override Seq skip(long n); @Override Seq onClose(Runnable closeHandler); @Override void close(); // These methods have no effect // ---------------------------- @Override default Seq sequential() { return this; } @Override default Seq parallel() { return this; } @Override default Seq unordered() { return this; } @Override default Spliterator spliterator() { return Iterable.super.spliterator(); } @Override default void forEach(Consumer action) { Iterable.super.forEach(action); } }