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 |