Following is a quick walk-through of Java Util Stream changes in Java 9.
New Stream methods java.util.stream.Stream has following new methods:
Stream.takeWhile(Predicate)
This method returns a stream which will not contain all the elements (from this stream) after
the provided Predicate returns false while processing the pipeline.
In following example once the predicate
!"orange".equals(s) returns false then further elements are skipped:
String[] fruits = {"apple", "banana", "orange", "mango", "peach"}; Stream<String> stream = Arrays.stream(fruits).takeWhile(s -> !"orange".equals(s)); stream.forEach(System.out::println);
apple
banana
|
Note that, for unordered stream, if there are multiple elements which match the provided predicate then this operation is
nondeterministic.
|
This method and Stream.filter() methods may sound similar at first
but they are different in that the filter() method just skips the unmatched elements and proceeds further,
on the other hand, the takeWhile() method skips all remaining elements once there's a match.
Following is the filter() example with the same stream and predicate:
String[] fruits = {"apple", "banana", "orange", "mango", "peach"}; Stream<String> stream = Arrays.stream(fruits).filter(s -> !"orange".equals(s)); stream.forEach(System.out::println);
apple
banana
mango
peach
|
Stream.dropWhile(Predicate) This method returns a stream which will only contain the elements (from this stream) after
the provided Predicate returns false while processing the pipeline.
In following example once the predicate
!"orange".equals(s) returns false further elements are accepted:
String[] fruits = {"apple", "banana", "orange", "mango", "peach"}; Stream<String> stream = Arrays.stream(fruits).dropWhile(s -> !"orange".equals(s)); stream.forEach(System.out::println);
orange
mango
peach
|
Stream<T> Stream.iterate(T, Predicate, UnaryOperator) This method returns a sequential stream which terminates the
iterative operation (provided by UnaryOperator) as soon as Predicate returns false.
Stream<String> iterate = Stream.iterate("-", s -> s.length() < 5, s -> s + "-"); iterate.forEach(System.out::println);
-
--
---
----
This is a sibling overload method of iterate(T seed, UnaryOperator f) (old one) which returns an infinite stream.
|
Stream<T> Stream.ofNullable(T) This method returns a sequential Stream containing a single element. If the provided
element is null then this method returns an empty Stream.
Stream<String> stream = Stream.ofNullable("anItem"); stream.forEach(System.out::println);
anItem
|
This method can be useful when we want to append a non-null single element to a stream. For example:
String nullableItem = "peach"; Stream<String> stream = Stream.of("apple", "banana", "orange"); Stream<String> stream2 = Stream.concat(stream, Stream.ofNullable(nullableItem)); stream2.forEach(System.out::println);
apple
banana
orange
peach
|
Also we do not need to take an extra step to check whether the element we are appending is
null or not null:
String nullableItem = null; Stream<String> stream = Stream.of("apple", "banana", "orange"); Stream<String> stream2 = Stream.concat(stream, Stream.ofNullable(nullableItem)); stream2.forEach(System.out::println);
apple
banana
orange
|
IntStream, LongStream and DoubleStream methods These stream classes also have the equivalent of the above methods (except for the ofNullable()
method).
For example
IntStream.of(2, 4, 6, 8, 9, 10, 11) .takeWhile(i -> i % 2 == 0) .forEach(System.out::println);
2
4
6
8
IntStream.of(2, 4, 6, 8, 9, 10, 11) .dropWhile(i -> i % 2 == 0) .forEach(System.out::println);
9
10
11
IntStream.iterate(0, i -> i < 10, i -> i + 1) .forEach(System.out::print);
0123456789
|
New Collectors methods The class java.util.stream.Collectors has following new methods:
Collectors.filtering(Predicate, Collector)
This method processes the provided Collector while applying the provided Predicate
to each input element and only accepting the elements for which the predicate returns true.
List<Integer> list = IntStream.of(2, 4, 6, 8, 10, 12) .boxed() .collect(Collectors.filtering(i -> i % 4 == 0, Collectors.toList())); System.out.println(list);
[4, 8, 12]
|
Collectors.flatMapping(Function, Collector) This method processes the provided Collector while applying the
provided mapping Function
to each input element.
This method can be applied in the situations where each element (or a member of the element)
of the original stream is convertible to a stream. It's a way to convert a member collection
to the flat elements.
List<Integer> list = Stream.of(List.of(1, 2, 3, 4), List.of(5, 6, 7, 8)) .collect(Collectors.flatMapping( l -> l.stream() .filter(i -> i % 2 == 0), Collectors.toList() )); System.out.println(list);
[2, 4, 6, 8]
|
Following example groups the lists of stream by the lists' sizes and maps each list to the flat elements of integer which are only divisible by 2:
Map<Integer, List<Integer>> map = Stream.of(List.of(1, 2, 3, 4, 5, 6), List.of(7, 8, 9, 10)) .collect( Collectors.groupingBy(Collection::size, Collectors.flatMapping( l -> l.stream() .filter(i -> i % 2 == 0), Collectors.toList() ))); System.out.println(map);
{4=[8, 10], 6=[2, 4, 6]}
|
|
|