我正在阅读几篇关于Java 8中提供的lambda表达式的博客和答案。
我无法弄清楚,是否有单位lambda表达式的运行时优势?
我复制了来自不同来源的以下文字,这对我来说太过混乱。
一个答案是 -
“lambdas不会创建新的范围,它们的范围与 封闭区块/环境“
在一个博客中 -
“使用lambda表达式没有运行时的好处,所以我会 谨慎使用它,因为我不介意写几行额外的 代码“。
来自另一个博客 -
“还有一个好处是lambda表达式顺序和并行执行 通过在方法“
中传递行为来支持
所以对我来说有很多困惑。 请帮我清楚这一点,以便在深入研究这些内容之前,我可以避免记住错误的方法。
我运行了以下代码,我可以说下面代码中的lambda表达式只是替代匿名内部类及其在主线程上运行。
List<Integer> list = new ArrayList<>();
list.add(12);
list.forEach(V -> {
System.out.println(V);
});
我们是否减少了时间复杂度或空间复杂度?
答案 0 :(得分:6)
“ lambdas不创建新范围,它们与封闭块/环境共享相同范围”是一个几乎正确的语句(它们确实创建了一个新范围,但不是内部类的方式do),但与运行时性能没有任何关系。这与代码的正确性有关。
在匿名内部类中,标识符可以通过词法范围解析,在周围范围内找到匹配项,或者通过继承,在匿名内部类的类层次结构中查找匹配项。在这种情况下解析标识符的规则很复杂,容易混淆。
此外,匿名类的主体创建一个新的范围,允许创建与周围上下文的局部变量同名的变量,遮蔽这些变量。
相比之下,lambda表达式就像它们所写的上下文中的其他表达式一样。它们不会从它们将被转换为的函数接口继承任何成员,它们无法创建遮蔽现有局部变量的新变量甚至{ {1}}和this
与周围环境中的含义相同:
与匿名类声明中出现的代码不同,名称的含义以及出现在lambda主体中的
super
和this
关键字以及引用声明的可访问性与周围的相同上下文(lambda参数引入新名称除外)。
因此,当您在同一个区块中使用表达式super
和x.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?