【问题标题】:How does Java 8 mapToInt ( mapToInt(e -> e) )improves performance exactly?Java 8 mapToInt ( mapToInt(e -> e) ) 如何准确地提高性能?
【发布时间】:2014-08-12 16:21:42
【问题描述】:

我正在阅读《Java 8 Lambdas》一书,作者有时说“尽可能使用原始的专用函数是个好主意,因为 性能优势。”。

他这里指的是mapToInt、mapToLong等

说实话,我不知道性能从何而来。

让我们考虑一个例子:

    // Consider this a very very long list, with a lot of elements
    List<Integer> list = Arrays.asList(1, 2, 3, 4);

    //sum it, flavour 1
    int sum1 = list.stream().reduce(0, (acc, e) -> acc + e).intValue();

    //sum it, flavour 2
    int sum2 = list.stream().mapToInt(e -> e).sum();

    System.out.println(sum1 + " " + sum2);

所以,在第一种情况下,我使用 reduce 对值求和,因此 BinaryOperator 函数将一直接收一个 int ( acc ) 和一个 Integer ( 集合的当前元素 ),然后对整数到 int (acc + e)

在第二种情况下,我使用 mapToInt,它将每个 Integer 拆箱成一个 int,然后对其求和。

我的问题是,第二种方法有什么优势吗? 另外,什么时候我可以使用 map,将 map 转换为 int 有什么意义?

是的,这只是糖语法还是有一些性能优势?如果有,请提供一些信息

问候,

【问题讨论】:

  • 与原语一起使用是一个优势,集合 api 通常与相应的对象对应物一起使用,因此可以避免
  • 是的,但对我来说,拆箱的数量是一样的。这就是为什么我看不出优势从何而来
  • 如果你追求最后一点的性能,你应该更喜欢mapToInt(Integer::intValue)而不是mapToInt(e -&gt; e)
  • @Holger 他们不是等价的吗? e -&gt; e 正在执行一个隐式拆箱操作,无论如何它都委托给 Integer.intValue
  • @Alexander 是的,它将编译为委派给intValue() 的代码,而Integer::intValue 将评估为无需该委派而直接调用intValue() 的函数。它们等价的,由于保存了一个委托级别,因此性能差异很小(非常小)。

标签: java lambda java-8 java-stream


【解决方案1】:

还有一个额外的拳击水平在进行

int sum1 = list.stream().reduce(0, (acc, e) -> acc + e).intValue();

因为归约函数是一个BinaryOperator&lt;Integer&gt; - 它传递了两个Integer 值,将它们拆箱,添加它们,然后重新装箱结果。 mapToInt 版本将列表中的Integer 元素拆箱一次,然后从那时起将原始int 值用作IntStream

【讨论】:

  • +1。当映射后有更多操作(过滤、归约、其他转换)链接时,这一点更为重要,这些操作都需要拆箱然后重新装箱。
  • 啊,是的,我有点忘了 acc 也是 Integer :) 谢谢你指出 Ian,JB 你对之后应用的其他操作是正确的
猜你喜欢
  • 2019-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 2020-12-08
  • 2020-03-26
  • 1970-01-01
相关资源
最近更新 更多