Useful features, and examples of Java's 8 Stream API
Stream represents a sequence of objects from a source, which supports aggregate operations. Following are the characteristics of a Stream −
-
Sequence of elements − A stream provides a set of elements of specific type in a sequential manner. A stream gets/computes elements on demand. It never stores the elements.
-
Source − Stream takes Collections, Arrays, or I/O resources as input source.
-
Aggregate operations − Stream supports aggregate operations like filter, map, limit, reduce, find, match, and so on.
-
Pipelining − Most of the stream operations return stream itself so that their result can be pipelined. These operations are called intermediate operations and their function is to take input, process them, and return output to the target. collect() method is a terminal operation which is normally present at the end of the pipelining operation to mark the end of the stream.
-
Automatic iterations − Stream operations do the iterations internally over the source elements provided, in contrast to Collections where explicit iteration is required.
Stream can not modify or mutate it's source. For example in Class stream will not add new values to collection.
Streams aren't depends on outer conditions.
Look for CreationExample.java for examples of creation Streams.
There is a posibility to create empty sequential stream. Stream's emptyness means that there is no elements in it.
Stream.empty();
There is a posibility to create empty sequential stream. Stream's emptyness means that there is no elements in it.
Stream.of(obj);
You can create stream from collection, sequential it or not depends on type of collection.
collection.stream();
It is possible to create streams from popular Java API's like for example regular expressions:
String sentence = "Java 8 Stream tutorial";
Stream<String> regExpStream = Pattern.compile("\\w").splitAsStream(sentence);
In the example below, we use Stream.iterate which allows us to call infinite streams, a stream with out a fixed size.
Stream.iterate(0, n -> n + 1).limit(2);
Stream.generate allows you to produce an infinite stream of values on demand. The code below will generate a stream of 5 random double numbers from 0 to 1 and we apply the limit otherwise the stream would be unbounded.
Stream generatedStream = Stream.generate(Math::random).limit(5L);
Stream.builder can create a stream of values that are added
Stream buildedStream = Stream.builder()
.add("Java 8")
.add("Stream")
.add("tutorial")
.build();
There is three types of operations in streams:
- Intermediate operations (distinct,filter,map,flatMap,peek,sorted,limit,skip,unordered,parallel,sequential)
- Terminal operations (allMatch,anyMatch,noneMatch,findAny,findFirst,forEach,iterator,reduce,collect) Difference is that
- Short-circuiting (find*,*Match,limit) e.g. 5 terminal commands-all match and find, and one limit command
Stream<T> distinct();
Marks Stream as distinct. All elements are distinct.
Stream<T> filter(Predicate<? super T> predicate);
Creates stream with all elements according to given Predicate<S>
.
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Applies function from type S to type T for every element of stream.
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
Converts stream with nested Data like Stream<String[]>
to Stream without nesting, e.g. Stream<String>
.
Stream<T> peek(Consumer<? super T> action);
Useful for Streams debugging, allows to look what data in some moments is processing.
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
Marks Stream as sorted. It becomes sorted.
Stream<T> limit(long maxSize);
Limit Stream to given size.
Stream<T> skip(long n);
Skip first nth elements of the Stream.
Stream<S> s.unordered();
Marks Stream as unordered. It becomes unordered.
Stream<S> s.parallel();
All future operations are multi-threaded.
Stream<S> s.sequential();
Marks Stream as sequential. All future operations are in single thread.
void forEach(Consumer<? super T> action);
Performs an given action Consumer<S>
for each element of the stream.
Object[] toArray();
Returns an array with elements of this stream.
T reduce(T identity, BinaryOperator<T> accumulator);
Optional<T> reduce(BinaryOperator<T> accumulator);
<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner);
Combines stream elements into one using BinaryOperator<Type>
.
<R> R collect(Supplier<R> supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);
Collects elements of stream into another container.
Optional<T> min(Comparator<? super T> comparator);
Finds the minimum element of the stream according to provided Comparator<? super T> comparator
.
Optional<T> max(Comparator<? super T> comparator);
Finds the maximum element of the stream according to provided Comparator<? super T> comparator
.
long count();
Counts number of elements in the stream.
boolean anyMatch(Predicate<? super T> predicate);
Returns boolean variable based on fact that any of stream's elements match provided Predicate<? super T> predicate
.
boolean allMatch(Predicate<? super T> predicate);
Returns boolean variable based on fact that all of stream's elements match provided Predicate<? super T> predicate
.
boolean noneMatch(Predicate<? super T> predicate);
Returns boolean variable based on fact that none of stream's elements match provided Predicate<? super T> predicate
.
Optional<T> findFirst();
Returns first element of the stream.
Optional<T> findAny();
Returns any element of the stream.