I thought that all stream pipelines written using flatMap can be converted to use mapMulti. Looks like I was wrong when the flatMap or mapMulti returns/operates on an infinite stream.
This is for educational purpose only
When we map an element to an infinite stream inside a flatMap followed by a limit(), then the stream pipeline is lazy and evaluates as per the required number of elements.
list.stream()
.flatMap(element -> Stream.generate(() -> 1))
.limit(3)
.forEach(System.out::println);
Output:
1
1
1
But when doing the same in a mapMulti, the pipeline is still lazy i.e., it doesn’t consume the infinite stream. But when running this in IDE (Intellij), it hangs and doesn’t terminate (I guess waiting for other elements consumption) and doesn’t come out of the stream pipeline execution.
With a mapMulti,
list.stream()
.mapMulti((element, consumer) -> {
Stream.generate(() -> 1)
.forEach(consumer);
})
.limit(3)
.forEach(System.out::println);
System.out.println("Done"); //Never gets here
Output:
1
1
1
But the last print (Done
) doesn’t get executed.
Is this the expected behaviour?
I couldn’t find any warning or points on infinite stream and mapMulti in Javadoc.
>Solution :
The advantage of mapMulti()
is that it consumes new elements which became a part of the stream, replacing the initial element (opposed to flatMap()
which internally generates a new stream for each element). If you’re generating a stream inside the mapMulti()
it should be consumed (i.e. executed). And you’ve created an infinite stream which can’t be fully consumed.
On the contrary, flatMap()
expects a function producing a stream, i.e. function only returns it not processes.
Here’s a quote from the API note that emphasizes the difference between the two operations:
API Note:
This method is similar to
flatMap
in that it applies a one-to-many
transformation to the elements of the stream and flattens the result
elements into a new stream. This method is preferable toflatMap
in
the following circumstances:
- When replacing each stream element with a small (possibly zero) number of elements. Using this method avoids the overhead of creating
a new Stream instance for every group of result elements, as required
byflatMap
.