简体   繁体   English

Java-Stream - 具有无限流的 mapMulti()

[英]Java-Stream - mapMulti() with Infinite Streams

I thought that all stream pipelines written using flatMap() can be converted to use mapMulti .我认为所有使用flatMap()编写的 stream 管道都可以转换为使用mapMulti Looks like I was wrong when the flatMap() or mapMulti() returns/operates on an infinite stream.flatMap()mapMulti()在无限 stream 上返回/操作时,看起来我错了。

Note: 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.当我们 map 一个元素到无限 stream 在flatMap()后跟一个limit()时,stream 管道是惰性的,并根据所需的元素数量进行评估。

list.stream()
    .flatMap(element -> Stream.generate(() -> 1))
    .limit(3)
    .forEach(System.out::println);

Output: Output:

1
1
1

But when doing the same in a mapMulti() , the pipeline is still lazy ie, 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.但是当在mapMulti()中做同样的事情时,管道仍然是惰性的,即它不会消耗无限的 stream。但是当在 IDE (Intellij) 中运行它时,它挂起并且不会终止(我想等待其他元素消耗)并且不会从 stream 管道执行中出来。

With a mapMulti() ,使用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: Output:

1
1
1

But the last print ( Done ) doesn't get executed.但是最后一个打印( Done )没有被执行。

Is this the expected behaviour?这是预期的行为吗? I couldn't find any warning or points on infinite stream and mapMulti() in Javadoc.我在 Javadoc 中找不到关于 infinite stream 和mapMulti()的任何警告或要点。

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 ). mapMulti()的优点是它消耗成为 stream 一部分的新元素,替换初始元素(与内部为每个元素生成新的 stream 的flatMap()相反)。 If you're generating a fully-fledged stream with a terminal operation inside the mapMulti() it should be executed.如果您在mapMulti()中生成一个带有终端操作的完整 stream,则应该执行它。 And you've created an infinite stream which can't terminate (as @Lino has pointed out in the comment ).并且您创建了一个无法终止的无限 stream(正如@Lino评论中指出的那样)。

On the contrary, flatMap() expects a function producing a stream, ie function only returns it not processes.相反, flatMap()期望 function 产生 stream,即 function 只返回它而不处理。

Here's a quote from the API note that emphasizes the difference between the two operations:这是API 注释中的一段引述,强调了两种操作之间的区别:

API Note: API 备注:

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 to flatMap in the following circumstances:该方法与flatMap类似,对stream的元素进行一对多的变换,将结果元素扁平化为新的stream。在以下情况下,该方法优于flatMap

  • When replacing each stream element with a small (possibly zero) number of elements.当用少量(可能为零)元素替换每个 stream 元素时。 Using this method avoids the overhead of creating a new Stream instance for every group of result elements, as required by flatMap .使用此方法可以避免为每组结果元素创建新的 Stream 实例的开销,如flatMap所要求的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM