Java 流收集与地图收集

Java 流收集与地图收集,java,java-8,java-stream,Java,Java 8,Java Stream,Stream中有一些方法,特别是在处理可以这样或那样写入的数值时。(同样的问题也适用于average()) 那么哪种方法更可取: DoubleSummaryStatistics result; result = stream() .collect( Collectors.summarizingDouble( weighter::weight ) ); vs 为什么 (在我看来,第一种方法的优点是只“访问”每个元素一次,而第二种方法的语义更清晰,但访问每个元素至少两次。但这是否

Stream
中有一些方法,特别是在处理可以这样或那样写入的数值时。(同样的问题也适用于
average()

那么哪种方法更可取:

DoubleSummaryStatistics result;

result = stream()
        .collect( Collectors.summarizingDouble( weighter::weight ) );
vs

为什么


(在我看来,第一种方法的优点是只“访问”每个元素一次,而第二种方法的语义更清晰,但访问每个元素至少两次。但这是否重要/正确?

summaryStatistics()提供了更多信息,但其性能可能不是预期的,取决于您希望获得的输出…

性能方面,第二种方法(映射然后汇总)似乎比第一种方法(使用收集器)更快:

基准代码:

@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; }
  }

}
@状态(Scope.Thread)
@基准模式(模式平均时间)
公共类SO26775395{
@参数({“10”、“1000”、“1000000”)int n;
列出权重;
@设置公共无效设置(){
权重=新随机数()。双倍(n)
.mapToObj(权重:新)
.collect(toList());
}
@基准公共DoubleSummaryStatistics收集器(){
返回weights.stream().collect(收集器.summaringdouble(Weighter::w));
}
@基准公共双汇总统计摘要(){
返回weights.stream().mapToDouble(Weighter::w).summaryStatistics();
}
公共静态类权重器{
私人决赛双w;
公共加权器(双w){this.w=w;}
公共双w(){return w;}
}
}
许多预定义的操作可能看起来是多余的,因为它们表示可以在流上直接访问的操作。但是,当您开始编写收集器时,它们是有意义的。例如:

Map<Department, DoubleSummaryStatistics> statsByDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment,
                                   Collectors.summarizingDouble(Employee::getSalary)));
Map statsByDept=employees.stream()
.collect(收集器)groupingBy(员工::getDepartment,
催收员:汇总双倍(员工::getSalary));

我认为没有优先选择的方法,两者都是正确的,这取决于你想要实现什么……不。它们都给出了相同的结果,所以第二个更干净、更快。我想知道为什么。基准测试看起来很有趣。你用了什么?
@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; }
  }

}
Map<Department, DoubleSummaryStatistics> statsByDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment,
                                   Collectors.summarizingDouble(Employee::getSalary)));