Java 8 lambda表达式在哪里评估?

Oom*_*ity 17 java lambda

lambda表达式是在我们编写它们的地方还是在任何其他Java类中进行评估的?

例如 :

Stream<Student> absent =  students.values().stream().filter(s -> !s.present());
Run Code Online (Sandbox Code Playgroud)

传递给过滤器方法的上述lambda表达式是否会在代码写入的给定类中立即执行,或者在另一个类中执行,并且与以传统编码样式编写代码相比,它将花费更多时间(以纳秒为单位)在Java 8之前?

Era*_*ran 16

传递到您的示例中的过滤器的方法的lambda表达式的身体不会在所有被执行,因为filter是中间操作中,仅获取执行Streams表示在终端操作结尾,例如collect,forEach等...

如果添加的终端操作,如收集的元素StreamList:

List<Student> absent =  students.values().stream().filter(s -> !s.present()).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

将为您的每个元素执行lambda表达式的主体Stream,以便终端操作能够生成其输出.

请注意,如果将Predicate接口的匿名类实例或其他实现传递给filter方法而不是lambda表达式,则此行为不会更改.


Eug*_*ene 15

编译源代码时,编译器将为invokedynamic您使用的lambda表达式插入字节代码指令.实际的实现(在您的情况下是a Predicate)将在运行时通过创建ASM.它运行时甚至不会出现在硬盘上 - 这意味着类在内存中生成,没有.class文件可用Predicate.例如,匿名类之间的差异很大 - class编译时会生成一个文件.

Predicate如果您运行示例,则可以看到生成的文件:

-Djdk.internal.lambda.dumpProxyClasses=/Your/Path/Here
Run Code Online (Sandbox Code Playgroud)

否则Eran的答案是正确的,Streams由终端操作驱动,如果不存在则不会执行任何操作.你应该完全阅读Holger关于更有趣的差异的答案.


Sud*_*han 5

该表达式是懒惰的评估,这意味着他们将只有当你真正尝试“终止”流实际上被评估-即,需要使用带有流,但回报别的东西,比如操作collectminmaxreduce,等其采取行动流作为输入,返回流作为输出通常是惰性的。