在Java中使用lambda表达式有什么运行时的好处吗?

时间:2018-01-22 05:48:13

标签: java lambda java-8

我正在阅读几篇关于Java 8中提供的lambda表达式的博客和答案。

我无法弄清楚,是否有单位lambda表达式的运行时优势?

我复制了来自不同来源的以下文字,这对我来说太过混乱。

一个答案是 -

  

“lambdas不会创建新的范围,它们的范围与   封闭区块/环境“

在一个博客中 -

  

“使用lambda表达式没有运行时的好处,所以我会   谨慎使用它,因为我不介意写几行额外的   代码“。

来自另一个博客 -

  

“还有一个好处是lambda表达式顺序和并行执行   通过在方法“

中传递行为来支持

所以对我来说有很多困惑。 请帮我清楚这一点,以便在深入研究这些内容之前,我可以避免记住错误的方法。

我运行了以下代码,我可以说下面代码中的lambda表达式只是替代匿名内部类及其在主线程上运行。

List<Integer> list = new ArrayList<>();
list.add(12);
list.forEach(V -> {
    System.out.println(V);
});

我们是否减少了时间复杂度或空间复杂度?

3 个答案:

答案 0 :(得分:6)

lambdas不创建新范围,它们与封闭块/环境共享相同范围”是一个几乎正确的语句(它们确实创建了一个新范围,但不是内部类的方式do),但与运行时性能没有任何关系。这与代码的正确性有关。

在匿名内部类中,标识符可以通过词法范围解析,在周围范围内找到匹配项,或者通过继承,在匿名内部类的类层次结构中查找匹配项。在这种情况下解析标识符的规则很复杂,容易混淆。

此外,匿名类的主体创建一个新的范围,允许创建与周围上下文的局部变量同名的变量,遮蔽这些变量。

相比之下,lambda表达式就像它们所写的上下文中的其他表达式一样。它们不会从它们将被转换为的函数接口继承任何成员,它们无法创建遮蔽现有局部变量的新变量甚至{ {1}}和this与周围环境中的含义相同:

JLS§15.27.2. Lambda Body
  

与匿名类声明中出现的代码不同,名称的含义以及出现在lambda主体中的superthis关键字以及引用声明的可访问性与周围的相同上下文(lambda参数引入新名称除外)。

因此,当您在同一个区块中使用表达式superx.foo(y)时,() -> x.foo(y)x是否相同y将会很明显两个表达式都有x,因此,在每种情况下它都是相同的y方法,对于匿名内部类,你不能说这很简单,因为你必须分析整个内部类及其首先是类型层次结构。

这使得lambda表达式非常适合您想要定义局部函数的场景,例如:将它作为参数传递给方法,甚至不考虑实际使用的foo。除了定义函数签名之外,接口本身不会影响lambda表达式。

但这也意味着可能存在lambda表达式无法涵盖的匿名类的用例。但lambda表达式的目的不是匿名内部类的一般替代。

在性能方面或易于并行处理时,shmosel’s answer已经说过了。如果我们不知道我们正在查看哪个操作/问题以及我们实际比较哪些解决方案,我们就无法做出这样的一般性陈述。

答案 1 :(得分:5)

  

lambdas不创建新范围,它们与封闭块/环境

共享相同的范围

我不确定这句话是什么意思。

  

使用lambda表达式

没有运行时的好处

相对于什么? Lambda可能比匿名类表现更好,但两者都不会胜过简单的控制流语句。

  

另一个好处lambda表达式顺序和并行执行通过在方法中传递行为来支持

Streams和lambdas启用声明性编程,这使得并行化更易于访问。因此,使用lambdas可以间接提高性能。

答案 2 :(得分:-2)

匿名内部类被编译为额外的.class文件,但lambda是动态转换的。这是一篇详细的帖子:How will Java lambda functions be compiled?