我打算利用在我的程序中使用并行流的好处,我想替换这样的循环:
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());
我的问题是,我在这里遇到cyclic inference
错误。我理解我应该从内部地图返回int
以与外部地图兼容,但我想返回Coordinate
对象(因此mapToObj
调用)。是否可以使用collect
而不使用forEach
构造?
答案 0 :(得分:4)
你想做的是这些事情:
首先,当您在map
上致电IntStream
时,它仍然会返回IntStream
,这不是您想要的。相反,也可以使用mapToObj
作为外部循环。
其次,内部循环返回一个不完整的Stream<Coordinate>
,我认为这也不是你想要的。所以,你也想在那上面调用.collect(Collectors.toSet())
。
最后,您需要将flatMap
Stream<Set<Coordinate>>
合并为一个Stream<Coordinate>
,然后您可以使用
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());
编辑:
实际上,忘记内在的collect
。只需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())
答案 1 :(得分:2)
您不需要收集两次。
问题是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())