[英]Can Java Streams transform a list of points into a list of their coordinates?
我在JavaFX 8程序中有Point3D流。 为了从中创建网格,我希望能够生成它们的(x,y,z)坐标列表。
通过传统的Java循环,这已经足够简单了。 (实际上,这几乎是微不足道的。)但是,将来,我可能会处理成千上万的积分; 我非常希望能够使用Java Stream API并通过并行流完成此任务。
我想我要找的是这个伪代码的大致等效项:
List<Double> coordinates = stream.parallel().map(s -> (s.getX(), s.getY(), s.getZ())).collect(Collectors.asList());
到目前为止,我还没有发现任何此类功能。 有人可以请我朝正确的方向推进吗?
您可以使用flatMap
:
List<Double> coordinates =
stream.parallel()
.flatMap(s -> Stream.of(s.getX(), s.getY(), s.getZ()))
.collect(Collectors.asList());
为什么? 即使有了“成千上万的点”,代码也将在极短的时间内完成,并且“使用并行流”将不会真正获得任何收益。
这听起来像是一个过早优化的完美示例,您可能会将代码复杂化为尚不存在的问题,并且至少在这种情况下不可能成为问题。
为了证明我的观点,我在下面创建了测试代码。
为了最大程度地减少GC运行的影响,我使用-Xms10g -Xmx10g
运行了此代码,并添加了显式的gc()
调用,因此测试运行使用“干净的状态”运行。
与往常一样,性能测试受JIT优化和其他因素的影响,因此提供了一个预热循环。
public static void main(String[] args) {
Random rnd = new Random();
List<Point3D> input = new ArrayList<>();
for (int i = 0; i < 10_000; i++)
input.add(new Point3D(rnd.nextDouble(), rnd.nextDouble(), rnd.nextDouble()));
for (int i = 0; i < 100; i++) {
test1(input);
test2(input);
}
for (int i = 0; i < 10; i++) {
long start1 = System.nanoTime();
test1(input);
long end1 = System.nanoTime();
System.gc();
long start2 = System.nanoTime();
test2(input);
long end2 = System.nanoTime();
System.gc();
System.out.printf("%.6f %.6f%n", (end1 - start1) / 1_000_000d, (end2 - start2) / 1_000_000d);
}
}
private static List<Double> test1(List<Point3D> input) {
List<Double> list = new ArrayList<>();
for (Point3D point : input) {
list.add(point.getX());
list.add(point.getY());
list.add(point.getZ());
}
return list;
}
private static List<Double> test2(List<Point3D> input) {
return input.stream().parallel()
.flatMap(s -> Stream.of(s.getX(), s.getY(), s.getZ()))
.collect(Collectors.toList());
}
结果
0.355267 0.392904
0.205576 0.260035
0.193601 0.232378
0.194740 0.290544
0.193601 0.238365
0.243497 0.276286
0.200728 0.243212
0.197022 0.240646
0.192175 0.239790
0.198162 0.279708
没有什么大的区别,尽管并行流似乎稍微慢一些。
另请注意,它在不到0.3 ms的时间内完成了10,000点。
没什么!
让我们尝试将计数从10,000增加到10,000,000(跳过预热):
433.716847 972.100743
260.662700 693.263850
250.699271 736.744653
250.486281 813.615375
249.722716 714.296997
254.704145 796.566859
254.713840 829.755767
253.368331 959.365322
255.016928 973.306254
256.072177 1047.562090
现在并行流有一定的降级。 它慢了3倍 。 这可能是由于额外的GC运行引起的。
结论:过早的优化是不好的!!!!
就您而言,您实际上使情况更糟。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.