Java provides a new additional package in Java 8 called java.util.stream. This package consists of classes, interfaces and enum to allows functional-style operations on the elements. You can use stream by importing java.util.stream package.
Stream does not store elements. It simply conveys elements from a source such as a data structure, an array, or an I/O channel, through a pipeline of computational operations.
Stream is functional in nature. Operations performed on a stream does not modify it’s source. For example, filtering a Stream obtained from a collection produces a new Stream without the filtered elements, rather than removing elements from the source collection.
Stream is lazy and evaluates code only when required.
The elements of a stream are only visited once during the life of a stream. Like an Iterator, a new stream must be generated to revisit the same elements of the source.
Java Stream Interface Methods
|boolean allMatch(Predicate<? super T> predicate)||It returns all elements of this stream which match the provided predicate. If the stream is empty then true is returned and the predicate is not evaluated.|
|boolean anyMatch(Predicate<? super T> predicate)||It returns any element of this stream that matches the provided predicate. If the stream is empty then false is returned and the predicate is not evaluated.|
|static ||It returns a builder for a Stream.|
|<R,A> R collect(Collector<? super T,A,R> collector)||It performs a mutable reduction operation on the elements of this stream using a Collector. A Collector encapsulates the functions used as arguments to collect(Supplier, BiConsumer, BiConsumer), allowing for reuse of collection strategies and composition of collect operations such as multiple-level grouping or partitioning.|
|It performs a mutable reduction operation on the elements of this stream. A mutable reduction is one in which the reduced value is a mutable result container, such as an ArrayList, and elements are incorporated by updating the state of the result rather than by replacing the result.|
|static ||It creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream. The resulting stream is ordered if both of the input streams are ordered, and parallel if either of the input streams is parallel. When the resulting stream is closed, the close handlers for both input streams are invoked.|
|long count()||It returns the count of elements in this stream. This is a special case of a reduction.|
|Stream||It returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.|
|static ||It returns an empty sequential Stream.|
|Stream||It returns a stream consisting of the elements of this stream that match the given predicate.|
|Optional||It returns an Optional describing some element of the stream, or an empty Optional if the stream is empty.|
Operations on streams
The filter() method accepts a Predicate to filter all elements of the stream. This operation is intermediate which enables us to call another stream operation (e.g. forEach()) on the result.
memberNames.stream().filter((s) -> s.startsWith("A")) .forEach(System.out::println);
The map() intermediate operation converts each element in the stream into another object via the given function.
The following example converts each string into an UPPERCASE string. But we can use map() to transform an object into another type as well.
memberNames.stream().filter((s) -> s.startsWith("A")) .map(String::toUpperCase) .forEach(System.out::println);
The sorted() method is an intermediate operation that returns a sorted view of the stream. The elements in the stream are sorted in natural order unless we pass a custom Comparator.
memberNames.stream().sorted() .map(String::toUpperCase) .forEach(System.out::println);
AMAN AMITABH LOKESH RAHUL SALMAN SHAHRUKH SHEKHAR YANA
Please note that the sorted() method only creates a sorted view of the stream without manipulating the ordering of the source Collection. In this example, the ordering of string in the member Names is untouched.
Terminal operations return a result of a certain type after processing all the stream elements.
Once the terminal operation is invoked on a Stream, the iteration of the Stream and any of the chained streams will get started. Once the iteration is done, the result of the terminal operation is returned.
The forEach() method helps in iterating over all elements of a stream and perform some operation on each of them. The operation to be performed is passed as the lambda expression.
The collect() method is used to receive elements from a steam and store them in a collection.
List<String> memNamesInUppercase = memberNames.stream().sorted() .map(String::toUpperCase) .collect(Collectors.toList()); System.out.print(memNamesInUppercase);
[AMAN, AMITABH, LOKESH, RAHUL, SALMAN, SHAHRUKH, SHEKHAR, YANA]
Various matching operations can be used to check whether a given predicate matches the stream elements. All of these matching operations are terminal and return a boolean result.
boolean matchedResult = memberNames.stream() .anyMatch((s) -> s.startsWith("A")); System.out.println(matchedResult); //true matchedResult = memberNames.stream() .allMatch((s) -> s.startsWith("A")); System.out.println(matchedResult); //false matchedResult = memberNames.stream() .noneMatch((s) -> s.startsWith("A")); System.out.println(matchedResult); //false
The count() is a terminal operation returning the number of elements in the stream as a long value.
long totalMatched = memberNames.stream() .filter((s) -> s.startsWith("A")) .count(); System.out.println(totalMatched); //2
The reduce() method performs a reduction on the elements of the stream with the given function. The result is an Optional holding the reduced value.
In the given example, we are reducing all the strings by concatenating them using a separator #.
Optional<String> reduced = memberNames.stream() .reduce((s1,s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println);
⌖ core java streams-api programming