我在JavaFX 8程序中有一个Point3D流。我想,为了从它们创建一个Mesh,能够生成一个(x,y,z)坐标列表。
通过传统的Java循环,这是一项非常简单的任务。 (实际上,这几乎是微不足道的。)但是,将来,我可能会处理成千上万的点数;我非常希望能够使用Java Stream API并使用并行流来完成此任务。
我想我正在寻找的是这个伪代码的粗略等价物:
List<Double> coordinates = stream.parallel().map(s -> (s.getX(), s.getY(), s.getZ())).collect(Collectors.asList());
到目前为止,我还没有找到这样的功能。有人可以帮我推动正确的方向吗?
答案 0 :(得分:4)
您可以使用flatMap
:
List<Double> coordinates =
stream.parallel()
.flatMap(s -> Stream.of(s.getX(), s.getY(), s.getZ()))
.collect(Collectors.asList());
答案 1 :(得分:0)
为什么呢?即使使用了数以万计的积分,这些代码也会在很短的时间内完成,而且你并没有真正获得任何东西&#34;并行流#34;
这听起来像是premature optimization的一个完美示例,在这种情况下,您可能会使代码复杂化而不是一个问题,而且至少在这种情况下不可能是一个。
为证明我的观点,我在下面创建了测试代码。
为了最大限度地减少GC运行的影响,我使用-Xms10g -Xmx10g
运行此代码,并添加了明确的gc()
调用,因此测试运行使用&#34; clean slate&#34;。
与往常一样,性能测试受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());
}
RESULT
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
没有重大区别,尽管并行流看起来有点慢 另请注意,对于10,000点,它在小于0.3毫秒内完成 它什么都没有!
让我们尝试将计数从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运行引起的。
结论:过早优化很糟糕!!!!
在你的情况下,你实际上做得更糟。