gpt4 book ai didi

java - 如何懒惰地评估嵌套的 flatMap

转载 作者:行者123 更新时间:2023-12-04 11:19:05 26 4
gpt4 key购买 nike

我试图从两个 中变出笛卡尔积潜在无限然后我通过 limit() 限制的流.
到目前为止,这(大约)是我的策略:

@Test
void flatMapIsLazy() {
Stream.of("a", "b", "c")
.flatMap(s -> Stream.of("x", "y")
.flatMap(sd -> IntStream.rangeClosed(0, Integer.MAX_VALUE)
.mapToObj(sd::repeat)))
.map(s -> s + "u")
.limit(20)
.forEach(System.out::println);
}
这不起作用。
显然,我的第二个流在第一次在管道上使用时就被当场进行了最终评估。它不会产生我可以按照自己的节奏使用的惰性流。
我认为 .forEach在来自 ReferencePipeline#flatMap 的这段代码中是罪魁祸首:
@Override
public void accept(P_OUT u) {
try (Stream<? extends R> result = mapper.apply(u)) {
if (result != null) {
if (!cancellationRequestedCalled) {
result.sequential().forEach(downstream);
}
else {
var s = result.sequential().spliterator();
do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstream));
}
}
}
}
我希望上面的代码返回 20 个元素,如下所示:
a
ax
axx
axxx
axxxx
...
axxxxxxxxxxxxxxxxxxx
但相反它崩溃了 OutOfMemoryError ,因为很长 Stream嵌套 flatMap急切地评估 (??) 并用重复字符串的不必要副本填满我的内存。如果不是 Integer.MAX_VALUE ,提供的值为 3,保持相同的限制为 20,预期输出将改为:
a
ax
axx
axxx
a
ay
ayy
ayyy
b
bx
bxx
bxxx
...
(up until 20 lines)
编辑:此时我刚刚使用惰性迭代器推出了我自己的实现。不过,我认为应该有一种方法可以用纯 Streams 做到这一点。
编辑 2:这已被承认为 Java 中的错误票 https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8267758%20

最佳答案

正如您已经写的那样,这已被视为错误。也许,它会在 Java 的 future 版本中解决。
但即使现在也可能有解决方案。它不是很优雅,只有在外部流中的元素数量和限制足够小时才可能可行。但它会在这些限制下工作。
让我首先通过转换外部 flatMap 来稍微修改您的示例。分为两个操作(一个 map 和一个 flatMap 具有身份,只做展平):

Stream.of("a", "b", "c")
.map(s -> Stream.of("x", "y")
.flatMap(sd -> IntStream.rangeClosed(0, Integer.MAX_VALUE)
.mapToObj(sd::repeat)))
.flatMap(s -> s)
.map(s -> s + "u")
.limit(20)
.forEach(System.out::println);
我们可以很容易地看到,我们需要的每个内部流不超过 20 个元素。所以我们可以将每个流限制为这个数量的元素。这将起作用(您应该使用变量或常量作为限制):
Stream.of("a", "b", "c")
.map(s -> Stream.of("x", "y")
.flatMap(sd -> IntStream.rangeClosed(0, Integer.MAX_VALUE)
.mapToObj(sd::repeat)))
.flatMap(s -> s.limit(20)) // limit each inner stream
.map(s -> s + "u")
.limit(20)
.forEach(System.out::println);
当然这样还是会产生过多的中间结果,不过在上面的限制下可能问题不大。

关于java - 如何懒惰地评估嵌套的 flatMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67666850/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com