[英]Streams collect vs. map collect
Stream
中有一些方法,尤其是在处理可以这种或那种方式写入的数值时。 (同样的问题适用于average()
)
那么哪种方法更可取:
DoubleSummaryStatistics result;
result = stream()
.collect( Collectors.summarizingDouble( weighter::weight ) );
与
result = stream()
.mapToDouble( weighter::weight )
.summaryStatistics();
为什么?
(正如我所看到的,第一个具有“访问”每个元素只有一次的优势,而第二个具有更清晰的语义但是至少访问每个元素两次。但这是否重要/正确?)
性能方面,似乎第二种方法(地图然后总结)比第一种方法(使用收集器)更快:
Benchmark (n) Mode Samples Score Error Units
c.a.p.SO26775395.collector 10 avgt 10 0.110 ± 0.004 us/op
c.a.p.SO26775395.collector 1000 avgt 10 9.134 ± 0.310 us/op
c.a.p.SO26775395.collector 1000000 avgt 10 9091.649 ± 274.113 us/op
c.a.p.SO26775395.summary 10 avgt 10 0.110 ± 0.003 us/op
c.a.p.SO26775395.summary 1000 avgt 10 5.593 ± 0.234 us/op
c.a.p.SO26775395.summary 1000000 avgt 10 5598.776 ± 153.314 us/op
基准代码:
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
public class SO26775395 {
@Param({"10", "1000", "1000000"}) int n;
List<Weighter> weights;
@Setup public void setup() {
weights = new Random().doubles(n)
.mapToObj(Weighter::new)
.collect(toList());
}
@Benchmark public DoubleSummaryStatistics collector() {
return weights.stream().collect(Collectors.summarizingDouble(Weighter::w));
}
@Benchmark public DoubleSummaryStatistics summary() {
return weights.stream().mapToDouble(Weighter::w).summaryStatistics();
}
public static class Weighter {
private final double w;
public Weighter(double w) { this.w = w; }
public double w() { return w; }
}
}
许多预定义的收集器可能看起来多余,因为它们代表可在Stream上直接访问的操作。 但是,当你开始创作收藏家时,它们才有意义。 例如:
Map<Department, DoubleSummaryStatistics> statsByDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.summarizingDouble(Employee::getSalary)));
summaryStatistics()为您提供了更多信息,但其性能可能并不理想,取决于您想要获得的输出...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.