Java 16 introduces a new Stream.mapMulti method which allows you to replace elements in a stream with multiple elements.
The example below shows how you can use mapMulti to replace each string in a stream with its uppercased and lowercased versions:
Stream.of("Twix", "Snickers", "Mars")
  .mapMulti((s, c) -> {
    c.accept(s.toUpperCase());
    c.accept(s.toLowerCase());
  })
  .forEach(System.out::println);
Output:
TWIX
twix
SNICKERS
snickers
MARS
mars
The same thing can also be achieved using flatMap like this:
Stream.of("Twix", "Snickers", "Mars")
  .flatMap(s -> Stream.of(s.toUpperCase(), s.toLowerCase()))
  .forEach(System.out::println);
So what is the difference between mapMulti and flatMap? According to the javadocs:
This method is preferable to flatMap 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 by flatMap.
 - When it is easier to use an imperative approach for generating result elements than it is to return them in the form of a Stream.
 
Inspecting the code for multiMap, we can see that it delegates to flatMap, however, it makes use of a SpinedBuffer to hold the elements before creating the stream, thus avoiding the overhead of creating new streams per group of result elements.
default <R> Stream<R> mapMulti(BiConsumer<? super T, ? super Consumer<R>> mapper) {
  Objects.requireNonNull(mapper);
  return flatMap(e -> {
    SpinedBuffer<R> buffer = new SpinedBuffer<>();
    mapper.accept(e, buffer);
    return StreamSupport.stream(buffer.spliterator(), false);
  });
}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.