Interface AccountService{
public void createAccount();
}
AccountService accountServiceAnonymous = new AccountService(){
public void createAccount(){
Account account = new Account();
save(account);
}
};
AccountService accountServiceLambda = () -> {
Account account = new Account();
save(account);
}
除了减少代码行数之外,在java 8中使用lambda表达式还有其他优点吗?
答案 0 :(得分:18)
添加@Bilbo在评论中提到的内容。在Java 1.7中,发布了一个名为invokedynamic
的新JVM Opcode,Java 8 Lambda使用了它。因此,以下代码将导致在编译代码时创建Anonymous类。可能<ClassName>$1.class
所以如果你有10个匿名类,那么在最后一个jar中还有10个类。
AccountService accountServiceAnonymous = new AccountService(){
public void createAccount(){
Account account = new Account();
save(account);
}
};
但Java 8 lambda使用invokedynamic
来调用lambdas,因此如果你有10个lambdas,它将不会导致任何匿名类,从而减少最终的jar大小。
AccountService accountServiceLambda = () -> {
Account account = new Account();
save(account);
}
答案 1 :(得分:6)
将lambdas(和方法引用)与Stream API和Java 8中添加的其他功能(例如Java 8)相结合时,可以看到它们的另一个优点。可选的。
考虑以下代码:
private void pushToFront(AbstractInfo contactInfo) {
registeredWindows.stream()
.filter(window -> window.getWindowId() == contactInfo.getId())
.findAny()
.ifPresent(Window::pushToFront);
}
该方法过滤与windowId匹配的已注册窗口列表,其中联系人的id返回Optional。如果列表包含具有匹配id的窗口,则可以使用Optional中的值,然后使用pushToFront方法。将其与相同的功能相比较,但用Java 7编写:
private void pushToFront(AbstractInfo contactInfo) {
for (Window window : registeredWindows) {
if (window.getWindowId() == contactInfo.getId() {
window.pushToFront();
}
}
}
至少对我来说,带有lambda表达式,流和方法引用的代码更简洁和可读(当你习惯使用流时)。上面的例子非常简单 - 但考虑一个,在Java 7中需要嵌套循环,多个条件语句等。不容易阅读甚至更难以忽略正在发生的事情。
Lambda然后允许人们充分利用Java 8的其他整洁功能,其中包括整洁,干净,高效且易于理解的代码。
最重要的是,您应该将lambda表达式视为更大整体的一部分,这些表达式本身很好,但与Java 8的其他“构建块”结合使用时更好。
答案 2 :(得分:4)
还有一个 - 与匿名类不同,lambdas不创建新范围,它们与封闭块/环境共享相同的范围。
所以:
访问封闭对象更容易 - 普通EnclosingClass.this
引用是指封闭类的实例(您不需要说Observable<Response> track(@Body RequestBody body);
)
没有shadowing问题(因为您无法定义与封闭范围中的变量同名的局部变量)
答案 3 :(得分:2)
lambda表达式的优点
答案 4 :(得分:1)
Lambdas提供的(更多)优势是懒惰(从而提高了性能):
在Lambda之前 ,一条日志语句如下所示:
?
无论是否启用跟踪,class Sample {
public static void setFieldsMap(int fieldTag,
Function< Integer, ? > messageGetter,
String fieldKey ) {
messageGetter.apply(fieldTag);
}
}
都会被调用,这会浪费CPU周期。
为了避免此类昂贵的调用,我们曾经写过:
logger.trace("Costly Metrics: {}", expensiveCompuatation());
尽管它满足了需求,但是现在代码看起来很丑陋,带有更多的expensiveCompuatation()
语句,导致代码膨胀。
在Lambdas 之后,现在log语句看起来简洁明了(没有if语句的周围),并允许延迟昂贵的操作:
if (logger.isTraceEnabled()) {
logger.trace("Costly Metrics: {}", expensiveCompuatation());
}
答案 5 :(得分:0)
除了这里所说的内容,并严格回答所提出的问题,重要的是将lambdas视为代码块&#34;除其他外,它可以作为参数传递。由于您可以删除重复代码,因此这提供了巨大的优势。
那是怎么回事?在上面由@Kitke提供的示例中, pushToFront (...)方法,如果需求存在,可能会稍微重构为模板,并用于通过任何条件过滤registeredWindows 即可。 lambda表达式窗口 - &gt; window.getWindowId()== contactInfo.getId(),在这种情况下可以作为参数传递。如果没有这个强大的功能,每次需要按不同条件过滤 registeredWindows 集合时,都必须编写 while 循环。巨大的收获,重新考虑你的代码。摘自:http://www.copypasteisforword.com/notes/lambda-expressions-in-java。在那里你可以找到另一个lambda用法的例子来删除重复的代码。