如何创建一个模拟嵌套循环行为的流,该循环初始化为1 +外循环的索引

时间:2017-08-30 13:58:21

标签: java collections java-8 nested java-stream

我有以下方法,它采用List<Point2D>并为每个点之间的每一行创建Line2D

public List<Line2D> getAllPointToPointLines() {
    List<Point2D> points = getAllPoints();
    List<Line2D> lines = new ArrayList<>();
    for (int i = 0; i < points.size(); i++) {
        for (int j = i + 1; j < points.size(); j++) {
            lines.add(new Line2D.Double(points.get(i), points.get(j)));
        }
    }
    return lines;
}

要通过创建Line2D(pointA, pointB)以及Line2D(pointB, pointA)来避免重复行,内部循环初始化为外部循环的当前索引的一个以上。

我最接近使用流来达到此行为的方法是以下方法。

public List<Line2D> getAllPointToPointLines() {
    return points.stream()
            .flatMap(i -> points.stream().filter(j -> !i.equals(j))
                    .map(j -> new Line2D.Double(i, j))).collect(toList());
}

然而,由于上述原因,这当然会产生重复的行。

我使用以下代码测试了@Eugene的答案:

    Stopwatch stopwatch = new Stopwatch();
    stopwatch.start();
    for (int i = 0; i < 100000; i++) {
        points.getAllPointToPointLines();
    }
    stopwatch.stop();
    System.out.println("Non-stream - " + stopwatch.getTimeString());

    stopwatch.reset();
    stopwatch.start();
    for (int i = 0; i < 100000; i++) {
        points.getAllPointToPointLinesStream();
    }
    stopwatch.stop();
    System.out.println("Stream - " + stopwatch.getTimeString());

通过@fge提供的优化,原始方法的输出大约为150ms,替代流方法的输出大约为650ms。

1 个答案:

答案 0 :(得分:4)

看起来你需要这样的东西(我还没有用你的用例编译完全

 int size = points.size();
 IntStream.range(0, size)
            .boxed()
            .flatMap(i -> IntStream.range(i + 1, size)
                                   .mapToObj(j -> new Line2D.Double(points.get(i), points.get(j))))
            .collect(Collectors.toList());