Java 8嵌套循环与流。

5

我有一个for循环在整数[][]map上进行迭代。 目前代码如下:

for(int i = 0; i < rows; i++) {
    for(int j = 0; j < columns; j++) {
        if(map[i][j] == 1)
            q.add(new Point(i,j));
    }
}        

假设我有List<List<Integer>> maps2d而不是二维数组,我该如何使用流进行操作呢?

目前为止,我得到了以下内容:

maps2d.stream()
      .forEach(maps1d -> maps1d.stream()
                               .filter(u -> u == 1)
                               .forEach(u -> {

                               }
      )
);

到这里为止是正确的吗? 如果是的话,我该如何计算ij以创建new Point(i,j)并将其添加到q中?

1个回答

4
如果您真的希望将流用于相同的目的,那么一种选项是使用嵌套的 IntStream 迭代索引。例如:
public static List<Point> foo(List<List<Integer>> map) {
  return IntStream.range(0, map.size()) // IntStream
      .mapToObj(
          i ->
              IntStream.range(0, map.get(i).size())
                  .filter(j -> map.get(i).get(j) == 1)
                  .mapToObj(j -> new Point(i, j))) // Stream<Stream<Point>>
      .flatMap(Function.identity()) // Stream<Point>
      .collect(Collectors.toList()); // List<Point>
}

个人而言,我觉得这并不是很易读。请注意,您仍然可以使用嵌套的for循环来处理列表,类似于您目前的解决方案:

public static List<Point> foo(List<List<Integer>> map) {
  List<Point> result = new ArrayList<>();
  for (int i = 0; i < map.size(); i++) {
    List<Integer> inner = map.get(i);
    for (int j = 0; j < inner.size(); j++) {
      if (inner.get(j) == 1) {
        result.add(new Point(i, j));
      }
    }
  }
  return result;
}

1
谢谢您澄清,普通的for循环答案更易读,同时也回答了问题。普通的for循环更易读,这是流API可能的一个例子,但会降低可读性。 - Reger05
天啊,我知道作者在设计流库时面临着许多限制,但是这段代码真的很糟糕。 - Alexander
@Alexander 这里的主要问题是在流式处理列表时记住索引,而流API似乎并不是为此设计的。我还喜欢使用Google风格的格式,就像我上面所做的那样,这可能对习惯其他风格的人来说有些陌生。 - Slaw
1
我的主要抱怨是需要区分StreamIntStream。在Java中,人们总是热衷于对象的强大功能,以及分配的廉价和GC“现在非常快”。然而,当涉及到它时,必须发明IntStream,并进行所有必要的工作来进行转换,这是因为JVM没有用户可定义的内联值类型,这将使Stream<int>/Stream<double>成为可能,并消除对IntStream/DoubleStream等的需求。 - Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接