Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何惰性地计算嵌套的flatMap_Java_Java Stream_Lazy Evaluation_Cartesian Product - Fatal编程技术网

Java 如何惰性地计算嵌套的flatMap

Java 如何惰性地计算嵌套的flatMap,java,java-stream,lazy-evaluation,cartesian-product,Java,Java Stream,Lazy Evaluation,Cartesian Product,我试图从两个潜在无限的流中变出一个笛卡尔积,然后通过limit()对其进行限制 到目前为止,这(大约)是我的策略: @测试 void flatMapIsLazy(){ “a”、“b”、“c”流 .flatMap(s->Stream.of(“x”、“y”) .flatMap(sd->IntStream.rangeClosed(0,整数.MAX_值) .mapToObj(sd::repeat))) .地图(s->s+“u”) .限额(20) .forEach(System.out::println)

我试图从两个潜在无限的流中变出一个笛卡尔积,然后通过
limit()
对其进行限制

到目前为止,这(大约)是我的策略:

@测试
void flatMapIsLazy(){
“a”、“b”、“c”流
.flatMap(s->Stream.of(“x”、“y”)
.flatMap(sd->IntStream.rangeClosed(0,整数.MAX_值)
.mapToObj(sd::repeat)))
.地图(s->s+“u”)
.限额(20)
.forEach(System.out::println);
}
这不管用

显然,我的第二个流在第一次用于管道时就在现场进行最终评估。它不会产生一个懒惰的流,然后我可以按照自己的速度消费

我认为这段代码中的
.forEach
应该归咎于
ReferencePipeline#flatMap

@覆盖
公共无效接受(P_OUT u){

try(Stream正如您已经编写的,这已经被认为是一个bug。也许,它将在Java的未来版本中得到解决

但即使是现在也可能有一个解决方案。它不是很优雅,只有在外部流中的元素数量和限制足够小的情况下才可能可行。但它将在这些限制下工作

首先,让我稍微修改一下您的示例,将外部
flatMap
转换为两个操作(一个
map
和一个
flatMap
带有标识,只执行展平操作):

我们可以很容易地看到,每个内部流不需要超过20个元素。因此,我们可以将每个流的元素数限制为这个数量。这将起作用(您应该使用变量或常量作为限制):


当然,这仍然会产生太多的中间结果,但在上述限制下,这可能不是一个大问题。

除了流大小之外,您是否尝试过只运行
“x”。重复(Integer.MAX\u值)
一次?在我的机器上,我得到一个OOM。也许这只是一个很糟糕的例子,但你不能期望它工作。除了上面的,
.flatMap(s->second)
无法工作。您正在尝试重用流。这几乎肯定会给您带来一个非法状态异常。与原始查询更真实的代码版本可以是:
stream.of(“a”、“b”、“c”).flatMap(s->stream.of(“x”、“y”).flatMap(sd->IntStream.rangeClosed(0,Integer.MAX_值)。mapToObj(sd::repeat)).map(s->s+“u”).limit(20).forEach(System.out::println);
,这会导致OOM。注意,它有嵌套的flatMap调用。@ernest_k是的,就是这样。我更改了问题代码!谢谢!:)我假设您会提供一些值(比如限制方法的整数)控制输出的大小。看到几个这样的值的预期输出会很有用。这很好!在我的实际测试代码中,它不起作用,因为我
flatMap
limit
在非常不同的位置和堆栈深度,因为内部和外部流是在不同的类中生成的。也许我可以使我不能在电话中来回走动,但有点达不到目的。无论如何,谢谢你的时间和回答。
a
ax
axx
axxx
axxxx
...
axxxxxxxxxxxxxxxxxxx
a
ax
axx
axxx
a
ay
ayy
ayyy
b
bx
bxx
bxxx
...
(up until 20 lines)
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);
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);