在mapToInt之后调用map会有什么好处,如果需要的话

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

    // 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();

}

}

以上是 在mapToInt之后调用map会有什么好处,如果需要的话 的全部内容, 来源链接: utcz.com/qa/420340.html

回到顶部