intermediate operations
or terminal operations
.java.util.stream.Stream
interface from a data source (collection, array, set of elements).
The Stream interface represents a sequence of elements supporting sequential and parallel aggregate operations.import java.util.Arrays; import java.util.stream.Stream; // Creates a stream from a set of values. Stream<Integer> integerStream1 = Stream.of(1, 2, 3); // Creates a stream from an array. Integer[] values = {1, 2, 3}; Stream<Integer> integerStream2 = Stream.of(values); Stream<Integer> integerStream3 = Arrays.stream(values); // Creates a stream from a list. Stream<Integer> integerStream4 = Arrays.asList(values).stream();
Stream
interface.import java.util.stream.Stream; Stream<Integer> integerStream1 = Stream.of(1, 2, 3); // The intermediate operation "filter" transforms a stream into another stream Stream<Integer> integerStream2 = integerStream1.filter(i -> i % 2 == 0); // The intermediate operation "map" transforms a stream into another stream Stream<String> stringStream = integerStream2.map(i -> String.valueOf(i));
collect
, reduce
, and count
, as well as short-circuiting operations like findFirst
and anyMatch
.import java.util.stream.Stream; // The terminal operation "count" produces a result long count = Stream.of(1, 2, 3).count(); // The terminal operation "forEach" produces a side effect Stream.of(1, 2, 3).forEach(System.out::println);
import java.util.stream.Stream; // filter and limit are intermediate operations; they won't be applied yet Stream<Integer> integerStream1 = Stream.of(1, 2, 3, 4, 5, 6).filter(i -> i % 2 == 0).limit(2); // forEach is a terminal operation; all intermediate operations along with the terminal operation will now be applied integerStream1.forEach(System.out::println);
Stream
instance, that stream is closed and cannot be reused.Stream
instance
after it has already been operated upon or closed, an exception will be thrown:"IllegalStateException: stream has already been operated upon or closed"
.import java.util.stream.Stream; Stream<Integer> integerStream1 = Stream.of(1, 2, 3); // OK: first operation on "integerStream1" Stream<Integer> integerStream2 = integerStream1.filter(i -> i % 2 == 0); // Runtime Exception: IllegalStateException - stream has already been operated upon or closed Stream<Integer> integerStream3 = integerStream1.filter(i -> i % 2 == 0); // Runtime Exception: IllegalStateException - stream has already been operated upon or closed long count = integerStream1.count(); // OK: first operation on "integerStream2" System.out.println(integerStream2.count()); // Runtime Exception: IllegalStateException - stream has already been operated upon or closed System.out.println(integerStream2.count());
import java.util.Arrays; Integer[] values = {1, 2, 3}; // stream returns a sequential Stream Arrays.stream(values).forEach(System.out::println); Arrays.asList(values).stream().forEach(System.out::println); // parallel/parallelStream returns a possibly parallel Stream Arrays.stream(values).parallel().forEach(System.out::println); Arrays.asList(values).parallelStream().forEach(System.out::println);
collect
(terminal operation)collect
method.<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
import java.util.function.BiConsumer; import java.util.function.Supplier; import java.util.stream.Stream; Stream<Integer> integerStream = Stream.of(1, 2, 3); Supplier<StringBuilder> supplier = StringBuilder::new; BiConsumer<StringBuilder, ? super Integer> accumulator = StringBuilder::append; BiConsumer<StringBuilder, StringBuilder> combiner = StringBuilder::append; StringBuilder stringBuilder = integerStream.collect(supplier, accumulator, combiner);
<R, A> R collect(Collector<? super T, A, R> collector);
import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; Stream<Integer> integerStream = Stream.of(1, 2, 3); // Collectors.toList() returns a Collector that accumulates elements into a List List<Integer> list = integerStream.collect(Collectors.toList());
map
(intermediate operation)map
applies the given function to each element of the stream and produces a new stream containing the results.<R> Stream<R> map(Function<? super T, ? extends R> mapper);
import java.util.stream.Stream; Stream<Integer> intStream = Stream.of(1, 2, 3); Stream<String> stringStream = intStream.map(String::valueOf); stringStream.forEach(System.out::println);
filter
(intermediate operation)filter
applies the given predicate to filter elements of the stream, retaining only those that match.Stream<T> filter(Predicate<? super T> predicate);
import java.util.stream.Stream; Stream<Integer> intStream1 = Stream.of(1, 2, 3, 4, 5); Stream<Integer> intStream2 = intStream1.filter(i -> i % 2 == 0); intStream2.forEach(System.out::println);
findFirst
/ findAny
(terminal operations)findFirst
returns the first element of the stream wrapped in an Optional
.Optional<T> findFirst();
findAny
returns any element of the stream wrapped in an Optional
, possibly the first but not guaranteed.Optional<T> findAny();
import java.util.Optional; import java.util.stream.Stream; Optional<Integer> firstValue = Stream.of(1, 2, 3).findFirst(); if (firstValue.isPresent()) { System.out.println(firstValue.get()); } Optional<Integer> anyValue = Stream.of(1, 2, 3).findAny(); anyValue.ifPresent(System.out::println);
anyMatch
/ allMatch
/ noneMatch
(terminal operations)anyMatch
returns true
if any element matches the predicate.boolean anyMatch(Predicate<? super T> predicate);
allMatch
returns true
if all elements match the predicate.boolean allMatch(Predicate<? super T> predicate);
noneMatch
returns true
if no elements match the predicate.boolean noneMatch(Predicate<? super T> predicate);
import java.util.stream.Stream; // anyMatch boolean anyMatch = Stream.of(1, 2, 3).anyMatch(i -> i % 2 == 1); System.out.println(anyMatch); // true // allMatch boolean allMatch = Stream.of(1, 2, 3).allMatch(i -> i % 2 == 1); System.out.println(allMatch); // false // noneMatch boolean noneMatch = Stream.of(1, 2, 3).noneMatch(i -> i % 2 == 1); System.out.println(noneMatch); // false
reduce
(terminal operation)reduce
performs a reduction on the elements of the stream using an accumulator function and returns an Optional
or a single value.Optional<T> reduce(BinaryOperator<T> accumulator);
T reduce(T identity, BinaryOperator<T> accumulator);
import java.util.Optional; import java.util.stream.Stream; // Sum using reduce with Optional Optional<Integer> sum1 = Stream.of(1, 2, 3, 4, 5).reduce((a, b) -> a + b); sum1.ifPresent(System.out::println); // 15 // Sum using reduce with identity int sum2 = Stream.of(1, 2, 3, 4, 5).reduce(0, (a, b) -> a + b); System.out.println(sum2); // 15
limit
/ skip
(intermediate operations)limit
returns a stream with at most the specified number of elements.Stream<T> limit(long maxSize);
skip
returns a stream with the first specified number of elements discarded.Stream<T> skip(long n);
import java.util.stream.Stream; // limit - only first 3 elements Stream.of(1, 2, 3, 4, 5).limit(3).forEach(System.out::println); // 1, 2, 3 // skip - first 2 elements Stream.of(1, 2, 3, 4, 5).skip(2).forEach(System.out::println); // 3, 4, 5 // skip and limit Stream.of(1, 2, 3, 4, 5).skip(2).limit(3).forEach(System.out::println); // 3, 4, 5
distinct
(intermediate operation)distinct
returns a stream with duplicate elements removed based on their equals()
method.Stream<T> distinct();
import java.util.stream.Stream; Stream.of(1, 1, 2, 3, 4, 4, 5).distinct().forEach(System.out::println); // 1, 2, 3, 4, 5
sorted
(intermediate operation)sorted
returns a stream with elements sorted in natural order or according to a provided Comparator
.Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
import java.util.Comparator; import java.util.stream.Stream; // Natural order sorting Stream.of(1, 3, 2, 5, 4, 1).sorted().forEach(System.out::println); // 1, 1, 2, 3, 4, 5 // Custom comparator - reverse order Stream.of(1, 3, 2, 5, 4, 1).sorted(Comparator.reverseOrder()).forEach(System.out::println); // 5, 4, 3, 2, 1, 1
java.util.stream
" package:BaseStream: BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable
public interface BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable { Iterator<T> iterator(); Spliterator<T> spliterator(); boolean isParallel(); S sequential(); S parallel(); S unordered(); S onClose(Runnable closeHandler); @Override void close(); }
Stream: Stream<T> extends BaseStream<T, Stream<T>>
BaseStream
" interface for object references.
It defines several methods for transformation, filtering, aggregation, etc. (filter, map, reduce, distinct, count, ...).public interface Stream<T> extends BaseStream<T, Stream<T>> { // Filtering operations (intermediate operations) Stream<T> filter(Predicate<? super T> predicate); // Mapping operations (intermediate operations) <R> Stream<R> map(Function<? super T, ? extends R> mapper); // count operations (terminal operations) long count(); // reduce operations (terminal operations) Optional<T> reduce(BinaryOperator<T> accumulator); // ... other methods }
IntStream: IntStream extends BaseStream<Integer, IntStream>
BaseStream
" interface for primitive int values.
It defines several methods for transformation, filtering, aggregation, etc. (filter, map, reduce, distinct, count, sum, average, ...).public interface IntStream extends BaseStream<Integer, IntStream> { // Filtering operations (intermediate operations) IntStream filter(IntPredicate predicate); // Mapping operations (intermediate operations) IntStream map(IntUnaryOperator mapper); // sum operations (terminal operations) int sum(); // average operations (terminal operations) OptionalDouble average(); // ... other methods }
LongStream: LongStream extends BaseStream<Long, LongStream>
BaseStream
" interface for primitive long values.
It defines several methods for transformation, filtering, aggregation, etc. (filter, map, reduce, distinct, count, sum, average, ...).public interface LongStream extends BaseStream<Long, LongStream> { // Filtering operations (intermediate operations) LongStream filter(LongPredicate predicate); // Mapping operations (intermediate operations) LongStream map(LongUnaryOperator mapper); // sum operations (terminal operations) long sum(); // average operations (terminal operations) OptionalDouble average(); // ... other methods }
DoubleStream: DoubleStream extends BaseStream<Double, DoubleStream>
BaseStream
" interface for primitive double values.
It defines several methods for transformation, filtering, aggregation, etc. (filter, map, reduce, distinct, count, sum, average, ...).public interface DoubleStream extends BaseStream<Double, DoubleStream> { // Filtering operations (intermediate operations) DoubleStream filter(DoublePredicate predicate); // Mapping operations (intermediate operations) DoubleStream map(DoubleUnaryOperator mapper); // sum operations (terminal operations) double sum(); // average operations (terminal operations) OptionalDouble average(); // ... other methods }