如何从 java 8 中的双重嵌套映射中收集对象?

How to collect objects from a doubly nested map in java 8?

我打算在我的程序中利用并行流的好处,我想像这样替换循环:

    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 错误。我知道我应该从内部地图 return 一个 int 与外部地图兼容,但我想 return 一个 Coordinate 对象(因此 mapToObj呼叫)。是否可以使用 collect 而不使用 forEach 结构来做到这一点?

你要做的是这些:

首先,当你在 IntStream 上调用 map 时,它仍然是 returns 一个 IntStream,这不是你想要的。相反,外循环也使用 mapToObj

其次,内部循环 returns 是一个不完整的 Stream<Coordinate>,我认为这也不是您想要的。因此,您也需要为此调用 .collect(Collectors.toSet())

最后,您需要 flatMapStream<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。只是 flatmapStream::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())