Intermediate Operations
An intermediate operation is an operation that allows further operations to be added to a Stream
. For example, filter
is an intermediate operation since additional operations can be added to a Stream
pipeline after filter
has been applied to the Stream
.
In the examples below, many of the lambdas could be replaced by method references (e.g. the lambda () → new StringBuilder can be replaced by a method reference StringBuilder::new ).
|
Common Operations
The following intermediate operations are accepted by a Stream
:
Operation | Parameter | Returns a Stream that: |
---|---|---|
|
|
contains only the elements that match the |
|
|
contains the results of applying the given |
|
- |
contains the distinct (i.e. unique) elements in the stream as per the element’s |
|
- |
contains the elements in the stream in sorted order as per the element’s |
|
|
contains the elements in the stream in sorted order as per the given |
|
|
contains the original elements in the stream but truncated to be no longer than the given |
|
|
contains the original elements in the stream but after discarding the given |
|
|
contains the elements of the |
|
|
contains the original elements in the stream but additionally letting the given |
Below are examples that demonstrate how these operations can be applied.
filter
Stream.of("B", "A", "C" , "B")
.filter(s -> s.equals("B"))
returns a Stream
with the elements "B" and "B" because only elements that are equal to "B" will pass the filter
operation.
map
Stream.of("B", "A", "C" , "B")
.map(s -> s.toLowerCase())
returns a Stream
with the elements "b", "a", "c" and "b" because each element will be mapped (converted) to its lower case representation.
distinct
Stream.of("B", "A", "C" , "B")
.distinct()
returns a Stream
with the elements "B", "A" and "C" because only unique elements will pass the distinct
operation.
sorted
Stream.of("B", "A", "C" , "B")
.sorted()
returns a Stream
with the elements "A", "B", "B" and "C" because the sort
operation will sort all elements in the stream in natural order.
Stream.of("B", "A", "C" , "B")
.sorted(Comparator.reverseOrder())
returns a Stream
with the elements "C", "B", "B" and "A" because the sort
operation will sort all elements in the stream according to the provided Comparator
(in reversed natural order).
limit
Stream.of("B", "A", "C" , "B")
.limit(2)
returns a Stream
with the elements "B" and "A" because after the two first elements the rest of the elements will be discarded.
skip
Stream.of("B", "A", "C" , "B")
.skip(1)
returns a Stream
with the elements "A", "C" and "B" because the first element in the stream will be skipped.
flatMap
Stream.of(
Stream.of("B", "A"),
Stream.of("C", "B")
)
.flatMap(Function.identity())
.forEachOrdered(System.out::println);
returns a Stream
with the elements "B", "A", "C" and "B" because the two streams (that each contain two elements) are "flattened" to a single Stream
with four elements.
Stream.of(
Arrays.asList("B", "A"),
Arrays.asList("C", "B")
)
.flatMap(l -> l.stream())
returns a Stream
with the elements "B", "A", "C" and "B" because the two lists (that each contain two elements) are "flattened" to a single Stream
with four elements. The lists are converted to sub-streams using the List::stream
mapper method.
Stream Property Operations
There are also a number of intermediate operations that controls the properties of the Stream
and has no effect on its actual content. These are:
Operation | Parameter | Returns a Stream that: |
---|---|---|
|
- |
is parallel (not sequential) |
|
- |
is sequential (not parallel) |
|
- |
is unordered (data might appear in any order) |
|
|
will run the provided |
parallel
Stream.of("B", "A", "C" , "B")
.parallel()
returns a Stream
with the elements "B", "A", "C" and "B" but, when consumed, elements in the Stream
may be propagated through the pipeline using different Threads. By default, parallel streams are executed on the default `ForkJoinPool
.
sequential
Stream.of("B", "A", "C" , "B")
.parallel()
.sequential()
returns a Stream
with the elements "B", "A", "C" and "B" that is not parallel.
unordered
Stream.of("B", "A", "C" , "B")
.unordered()
returns a Stream
with the given elements but not necessary in any particular order. So when consumed, elements might be encountered in any order, for example in the order "C", "B", "B", "A". Note that unordered
is just a relaxation of the stream requirements. Unordered streams can retain their original element order or elements can appear in any other order.
Map to Primitive Operations
There are also some intermediate operations that maps a Stream
to one of the special primitive stream types; IntStrem
, LongStream
and DoubleStream
:
Operation | Parameter | Returns a Stream that: |
---|---|---|
|
|
is an |
|
|
is a |
|
|
is a |
|
|
contains the |
|
|
contains the |
|
|
contains the |
In many cases, primitive streams provide better performance but can only handle streams of: int , long and double .
|
mapToInt
Stream.of("B", "A", "C" , "B")
.mapToInt(s -> s.hashCode())
returns an IntStream
with the int
elements 66, 65, 67 and 66. (A is 65, B is 66 and so on)
mapToLong
Stream.of("B", "A", "C", "B")
.mapToLong(s -> s.hashCode() * 1_000_000_000_000l)
returns a LongStream
with the long
elements 66000000000000, 65000000000000, 67000000000000 and 66000000000000.
mapToDouble
Stream.of("B", "A", "C", "B")
.mapToDouble(s -> s.hashCode() / 10.0)
returns a DoubleStream
with the double
elements 6.6, 6.5, 6.7 and 6.6.
=== flatMapToInt
Stream.of(
IntStream.of(1, 2),
IntStream.of(3, 4)
)
.flatMapToInt(s -> s.map(i -> i + 1))
returns an IntStream
with the int
elements 2, 3, 4 and 5 because the two `IntStream`s where flattened to one stream whereby 1 was added to each element.
Primitive Operations
Primitive streams (like IntStream
and LongStream
) provide similar functionality as ordinary streams but usually the parameter count and types differ so that primitive streams can accept more optimized function variants.
Here is a table of some additional Intermediate Operations that primitive Streams can take:
Operation | Parameter | Returns a Stream that: |
---|---|---|
|
- |
contains the boxed elements in the original stream (e.g. an |
|
- |
contains the elements in the original stream converted to |
|
- |
contains the elements in the original stream converted to |
boxed
IntStream.of(1, 2, 3, 4)
.boxed()
returns a Stream
with the Integer
elements 1, 2, 3 and 4 because the original int
elements were boxed to their corresponding Integer
elements.
Java 9 Operations
Two new intermediate operations were introduced in Java 9. Since these methods were added to the Stream
interface with default implementations, these methods can be used by any Stream
implementation written in either Java 8 or Java 9.
Operation | Parameter | Returns a Stream that: |
---|---|---|
|
|
contains the elements in the original stream until the the first one fails the |
|
|
contains the elements in the original stream dropping all elements until the the first one fails the |