我正在尝试计算列表中值的平方和。
以下是三个均计算所需值的变体。
我想知道哪个是最有效的。我期待第三个
自动装箱仅执行一次,因此效率更高。

    // sum of squares
    int sum = list.stream().map(x -> x * x).reduce((x, y) -> x + y).get();
    System.out.println("sum of squares: " + sum);

    sum = list.stream().mapToInt(x -> x * x).sum();
    System.out.println("sum of squares: " + sum);

    sum = list.stream().mapToInt(x -> x).map(x -> x * x).sum();
    System.out.println("sum of squares: " + sum);

最佳答案

如有疑问,请进行测试!使用jmh,我在100k元素列表中得到以下结果(以微秒为单位,更好):

Benchmark                        Mode  Samples     Score    Error  Units
c.a.p.SO32462798.for_loop        avgt       10   119.110    0.921  us/op
c.a.p.SO32462798.mapToInt        avgt       10   129.702    1.040  us/op
c.a.p.SO32462798.mapToInt_map    avgt       10   129.753    1.516  us/op
c.a.p.SO32462798.map_reduce      avgt       10  1262.802   12.197  us/op
c.a.p.SO32462798.summingInt      avgt       10   134.821    1.203  us/op

因此,从快到慢都有:
  • for(int i : list) sum += i*i;
  • mapToInt(x -> x * x).sum()mapToInt(x -> x).map(x -> x * x).sum()
  • collect(Collectors.summingInt(x -> x * x))
  • map(x -> x * x).reduce((x, y) -> x + y).get()

  • 请注意,结果在很大程度上取决于JIT优化。如果映射中的逻辑更加复杂,则某些优化可能不可用(较长的代码=较少的内联),在这种情况下,流的版本可能比for循环花费4-5倍的时间-但是,如果该逻辑占用大量CPU资源,差异将再次减小。对您的实际应用程序进行性能分析将为您提供更多信息。

    基准代码供引用:
    @State(Scope.Benchmark)
    @BenchmarkMode(Mode.AverageTime)
    public class SO32462798 {
    
      List<Integer> list;
    
      @Setup public void setup() {
        list = new Random().ints(100_000).boxed().collect(toList());
      }
    
      @Benchmark public int for_loop() {
        int sum = 0;
        for (int i : list) sum += i * i;
        return sum;
      }
    
      @Benchmark public int summingInt() {
        return list.stream().collect(Collectors.summingInt(x -> x * x));
      }
    
      @Benchmark public int mapToInt() {
        return list.stream().mapToInt(x -> x * x).sum();
      }
    
      @Benchmark public int mapToInt_map() {
        return list.stream().mapToInt(x -> x).map(x -> x * x).sum();
      }
    
      @Benchmark public int map_reduce() {
        return list.stream().map(x -> x * x).reduce((x, y) -> x + y).get();
      }
    }
    

    关于java - 在mapToInt之后调用map是否有任何优势,如果需要的话,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32462798/

    10-10 01:01