在mapToInt之后调用map是否有任何优势,如果需要的话 [英] Is there any advantage of calling map after mapToInt, where ever required

查看:575
本文介绍了在mapToInt之后调用map是否有任何优势,如果需要的话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试计算列表中值的平方和。
以下是三个变量,它们都计算所需的值。
我想知道哪一个效率最高。我期待第三个
更高效,因为自动装箱只进行一次。

I am trying to calculate the sum of squares of values in the list. Below are three variations which all calculates the required value. I want to know which one is the most efficient. I am expecting the third one to be more efficient as auto boxing is only done once.

    // 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元素列表中得到以下结果(以微秒为单位,越小越好):

When in doubt, test! Using jmh, I get the following results on a list of 100k elements (in microseconds, smaller is better):

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

所以你有,从更快到更慢:

So you have, from faster to slower:


  • 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()

  • for(int i : list) sum += i*i;
  • mapToInt(x -> x * x).sum() and 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重的话差异将再次减少。分析您的实际应用程序将为您提供更多信息。

Note that the results are very much dependent on the JIT optimisations. If the logic in the mapping is more complex, some of the optimisations may be unavailable (longer code = less inlining) in which case the streams versions may take 4-5x more time than the for loop - but if that logic is CPU heavy the difference will reduce again. Profiling your actual application will give you more information.

基准代码供参考:

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

这篇关于在mapToInt之后调用map是否有任何优势,如果需要的话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆