如何在Java8中从双嵌套映射中收集对象?

如何在Java8中从双嵌套映射中收集对象?,java,java-8,java-stream,Java,Java 8,Java Stream,我计划在我的程序中利用使用并行流的好处,我想替换如下循环: for (int gridY = gridYFrom; gridY <= gridYTo; gridY++) { for (int gridX = gridXFrom; gridX <= gridXTo; gridX++) { coordinates.add(Coordinate.from(gridX, gridY)); } } IntStre

我计划在我的程序中利用使用并行流的好处,我想替换如下循环:

    for (int gridY = gridYFrom; gridY <= gridYTo; gridY++) {
        for (int gridX = gridXFrom; gridX <= gridXTo; gridX++) {
            coordinates.add(Coordinate.from(gridX, gridY));
        }
    }
    IntStream.rangeClosed(gridYFrom, gridYTo).parallel().map(y -> 
        IntStream.rangeClosed(gridXFrom, gridXTo).mapToObj(x -> {
            return Coordinate.from(x, y);
        }
    )).collect(Collectors.toSet());

我的问题是这里有一个
循环推理
错误。我知道我应该从内部映射返回一个
int
,以便与外部映射兼容,但我想返回一个
坐标
对象(因此调用
mapToObj
)。是否可以使用
collect
而不使用
forEach
构造来执行此操作?

您要做的是:

首先,当您在
IntStream
上调用
map
时,它仍然返回一个
IntStream
,这不是您想要的。相反,对于外部循环也使用
mapToObj

其次,内部循环返回一个不完整的
,我假设这也不是您想要的。因此,您还需要调用
.collect(Collectors.toSet())

最后,您需要
flatMap
转换为单个
,您可以使用

stream.flatmap(Set::stream);
这一切归结为

IntStream.rangeClosed(0, 10).parallel().mapToObj(y ->
    IntStream.rangeClosed(0, 20).mapToObj(x -> 
        Coordinate.from(x,y)).collect(Collectors.toSet())
).flatMap(Set::stream).collect(Collectors.toSet());
编辑: 实际上,忘记内部的
收集
。只需
flatmap
Stream::sequential

你最终会得到

IntStream.rangeClosed(0, 10).parallel().mapToObj(y -> 
    IntStream.rangeClosed(0, 20).mapToObj(x -> 
        Coordinate.from(x, y))).flatMap(Stream::sequential).collect(Collectors.toSet())

您要做的是以下几件事:

首先,当您在
IntStream
上调用
map
时,它仍然返回一个
IntStream
,这不是您想要的。相反,对于外部循环也使用
mapToObj

其次,内部循环返回一个不完整的
,我假设这也不是您想要的。因此,您还需要调用
.collect(Collectors.toSet())

最后,您需要
flatMap
转换为单个
,您可以使用

stream.flatmap(Set::stream);
这一切归结为

IntStream.rangeClosed(0, 10).parallel().mapToObj(y ->
    IntStream.rangeClosed(0, 20).mapToObj(x -> 
        Coordinate.from(x,y)).collect(Collectors.toSet())
).flatMap(Set::stream).collect(Collectors.toSet());
编辑: 实际上,忘记内部的
收集
。只需
flatmap
Stream::sequential

你最终会得到

IntStream.rangeClosed(0, 10).parallel().mapToObj(y -> 
    IntStream.rangeClosed(0, 20).mapToObj(x -> 
        Coordinate.from(x, y))).flatMap(Stream::sequential).collect(Collectors.toSet())

你不需要收集两次。 不幸的是,
IntStream
与java中的其他流不同。因此,您必须首先将其转换为普通流,然后才能执行
flatMap

IntStream.rangeClosed(gridYFrom, gridYTo)
   .mapToObj( y -> Integer.valueOf(y) )
   .flatMap( y -> 
      IntStream.rangeClosed(gridXFrom, gridXTo)
         .mapToObj(x ->  Coordinate.from(x,y))
   )
   .collect(Collectors.toSet())

你不需要收集两次。 不幸的是,
IntStream
与java中的其他流不同。因此,您必须首先将其转换为普通流,然后才能执行
flatMap

IntStream.rangeClosed(gridYFrom, gridYTo)
   .mapToObj( y -> Integer.valueOf(y) )
   .flatMap( y -> 
      IntStream.rangeClosed(gridXFrom, gridXTo)
         .mapToObj(x ->  Coordinate.from(x,y))
   )
   .collect(Collectors.toSet())

太好了,谢谢!我发现我需要收集两次,但另一个
mapToObj
仍然是个问题。请检查我的编辑。我完全忘记了
Stream::sequential
。为什么要使用
Stream::sequential
函数来平面映射内部流?只需使用
flatMap(s->s)
。太好了,谢谢!我发现我需要收集两次,但另一个
mapToObj
仍然是个问题。请检查我的编辑。我完全忘记了
Stream::sequential
。为什么要使用
Stream::sequential
函数来平面映射内部流?只需使用
flatMap(s->s)
。您可以使用
.boxed()
而不是
。mapToObj(y->Integer.valueOf(y))
您可以使用
.boxed()
而不是
。mapToObj(y->Integer.valueOf(y))