如何在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))