Lambda表达式和匿名类之间的实现差异/优化

use*_*903 12 java lambda java-8 java-stream

让我们假设我想迭代一组对象.

List<String> strmap = ...
//Without lambdas
strmap.stream().filter(new Predicate<String>() {
      public boolean test(String string) {
          return string.length == 10;
      }
}.forEach(new Consumer<String>() {
      public void accept (String string) {
          System.out.println("string " + string + " contains exactly 10 characters");
      }
} 
//With lambdas
strmap.stream()
      .filter(s -> s.length == 10)
      .forEach(s -> System.out.println("string " + s + " contains exactly 10 characters");
Run Code Online (Sandbox Code Playgroud)

第二个例子(没有lambdas)如何工作?每次调用代码时都会创建一个新对象(Predicate和Consumer),java jit编译器可以优化lambda表达式多少?为了获得更好的性能,我应该将所有lambdas声明为变量并且始终只传递引用吗?

private Predicate<String> length10 = s -> s.length == 10;
private Consumer<String> printer = s -> { "string " + s + " contains exactly 10 characters"; }

strmap.stream()
      .filter(length10)
      .forEach(printer);
Run Code Online (Sandbox Code Playgroud)

Lou*_*man 6

第二个例子(没有lambdas)如何工作?每次调用代码时都会创建一个新对象(Predicate和Consumer),java jit编译器可以优化lambda表达式多少?为了获得更好的性能,我应该将所有lambdas声明为变量并且始终只传递引用吗?

JIT的工作就是让它不必担心任何问题.例如,JIT可以(并且,我相信,将)使其s -> s.length == 10自动变为静态常量,因此它在整个类中重复使用,而不仅仅是该实例.它甚至可以在其他使用相同lambda的类中重用.

lambdas的全部意义在于你应该编写最简单的代码,JIT可以自由地做任何需要它来提高效率.例如,这就是为什么lambda是使用生成invokedynamic而不是简单地去除匿名内部类的原因.

写出简单的代码; 相信JIT做正确的事.这就是它的用途. 也就是说,如果你想要压倒性的,复杂的细节,这几乎肯定是最好的来源.

  • 由于`s - > s.length()== 10`是不变的,它总是变成一个常数,而不需要JIT的帮助.[This](http://stackoverflow.com/q/27524445/2711488)甚至适用于解释模式...... (3认同)
  • 不,[`LambdaMetafactory`](http://docs.oracle.com/javase/8/docs/api/?java/lang/invoke/LambdaMetafactory.html)是一个普通的Java类,它使用井生成字节码已知的ASM库.当第一次实例化lambda表达式时,您甚至可以使用Java调试器逐步执行它.但由于`invokedynamic`指令的工作方式,后续执行将使用第一次调用的结果,该调用是常量句柄或工厂方法/构造函数调用. (2认同)
  • 这取决于元工厂返回的内容.在无状态lambda的情况下,它将返回一个[包含常量的句柄](http://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandles.html#constant-java .lang.Class-java.lang.Object-)其评估仅仅意味着"返回常量".在捕获lambda的情况下,句柄确实代表可执行代码,该代码又生成lambda实例,即工厂方法或构造函数调用. (2认同)