验证preso中关于java8lambdas性能的语句

验证preso中关于java8lambdas性能的语句,java,performance,lambda,Java,Performance,Lambda,请从34英尺到40英尺观看: 它基本上声称,这两者之间存在着显著的性能差异 public class _14 { final String pattern; public _14(String pattern) { this.pattern = pattern; } public List<String> allMatchingElements(final List<String> elements) {

请从34英尺到40英尺观看:

它基本上声称,这两者之间存在着显著的性能差异

public class _14 {
    final String pattern;

    public _14(String pattern) {
        this.pattern = pattern;
    }

    public List<String> allMatchingElements(final List<String> elements) {
        return elements.stream()
                       .filter(e -> e.contains(pattern))
                       .collect(toList());
    }
}
public class\u 14{
最终字符串模式;
公共14(字符串模式){
这个模式=模式;
}
公共列表所有匹配元素(最终列表元素){
返回元素。stream()
.filter(e->e.contains(模式))
.collect(toList());
}
}

public class\u 14{
最终字符串模式;
公共14(字符串模式){
这个模式=模式;
}
公共列表所有匹配元素(最终列表元素){
最终字符串模式=this.pattern;
返回元素。stream()
.filter(e->e.contains(模式))
.collect(toList());
}
}
执行lambda捕获“拥有”lambda的实例(根据presenter为有状态)和lambda捕获局部变量(根据presenter为无状态)之间是否真的存在很大的性能差异


或者,重要的区别只是捕获(实例或局部变量)lambda(有状态)和非捕获lambda(无状态)之间的区别?正如本演示(幻灯片#32)中所述:。

您的怀疑是有道理的

lambda表达式的对象是否是无状态的并不取决于目标方法是否为static。更糟糕的是,演示者关注的是一个未指定的、特定于编译器的实现细节

捕获
的lambda表达式可以编译为实例方法或
静态
方法,该方法接收对象作为参数。AFAIR,早期版本的
javac
使用后一种形式,因此使用这样的编译器,您甚至不会在视频中看到这样的代码更改

您可以通过将代码重写为以下内容来模拟这种行为:

public List<String> allMatchingElements(final List<String> elements) {
    final _14 arg = this;
    return elements.stream()
                   .filter(e -> e.contains(arg.pattern))
                   .collect(toList());
}
公开列出所有匹配元素(最终列表元素){
最终_14arg=此;
返回元素。stream()
.filter(e->e.contains(参数模式))
.collect(toList());
}
现在,这个lambda表达式不捕获
this
,而是一个局部变量
arg
,它包含作为第一个参数传递给合成
静态
方法的同一个对象,但是应该很明显,与调用合成实例方法的
this
捕获lambda没有区别

因此,在该演示文稿中所做的更改将影响生成的实例是捕获
实例还是捕获
模式
字符串,这不会改变lambda表达式的捕获性质以及当前JRE实现将在每个捕获过程中创建新实例的事实。但是无论如何,对于大多数用例来说,性能影响可以忽略不计

如果可以,您应该避免捕获
的唯一情况是,假设lambda表达式的实例可能具有更长的生存期,因为捕获
可能会阻止其垃圾收集

对于该演示的用例中的临时对象,无需担心。在当前实现中,您将使用所示的流操作创建六个临时对象实例,但演示者将重点放在为lambda表达式创建的单个临时实例上,这可能被视为一个具有讽刺意味的转折点

public List<String> allMatchingElements(final List<String> elements) {
    final _14 arg = this;
    return elements.stream()
                   .filter(e -> e.contains(arg.pattern))
                   .collect(toList());
}