编程中提到的LambdaExpression就是指匿名函数或闭包。匿名函数就是没有函数名称的函数,例如JavaGUI编程中的监听器。闭包就是函数内部的函数,闭包使变量脱离函数作用域也能被访问到。
JavaLambda的实现
🔹Lambda语法
一般格式:(param1,param2,…)->{…},param1、param2代表方法的入参,用逗号分隔。->代表指向方法实现体。{}用来存放方法体的内容。
例如:两个整数和的方法,lambda表示:(a,b)->{returna+b;};
简化格式:当lambda表示的方法只有一个入参时,可以省略括号()。当lambda表示的方法体只有一行代码时,可以省略大括号{},方法返回类型为boolean时,还可以省略return关键字。注意:当没有输入参数时,括号不能省略。
例如:打印对象内容,lambda表示:a->System.out.println(a)。
🔹方法引用(Lambda语法糖)
方法引用本质上就是lambdaexpression的语法糖,我们可以使用更加精简的代码来编写程序。如果Java代码库方法或自定义方法的输入、输出类型及业务逻辑恰好与将要编写的lambdaexpression一致,我们可以直接使用存在的方法。
例如:打印对象的内容,methodreference表示:System.out::println
🔹函数式接口
LambdaExpression本身并没有意义,需要依赖上下文存在。
例如:Runnablerunnable=()->{};//代表线程,Closeablecloseable=()->{};//代表文件。
在Java中上下文指函数式接口,如果一个接口有且仅有一个有效的抽象方法,那么该接口即为函数式接口。与Object类方法签名一致的抽象方法不是有效方法。Java提供的@FunctionalInterface检查注解,通过该注解可以让Java编译器帮我们检查某接口是否为函数式接口,但是并不是只有@FunctionalInterface注解标注的接口才是函数式接口,只要接口满足函数式接口的定义即为函数式接口。
Java为实现自己的功能提供了大量的函数式接口,比如:Consumer接口(接收一个任意类型输入参数,没有返回值)、Predicate接口(接收一个任意类型输入参数,返回boolean类型值)、Function接口(接收一个任意类型输入参数,返回一个任意类型的值)。这些接口都位于java.util.function包中,我们可以直接拿来使用。
注意:从Java8开始,接口不但可以定义抽象方法,还可以定义默认方法与静态方法,提供默认方法和静态方法的主要原因是满足Java版本的兼容性。
总之,LambdaExpression、MethodReference、ConstructReference必须依附于函数式接口存在,它们本质上都是函数式接口的对象,这是JavaLambda与其它语言的本质区别。在Java中,LambdaExpression是对象,而在其它语言中,比如Java语言是函数。
JavaLambda的应用
🔵Stream(管道流):
Stream就是流的意思,熟悉Unix、Linux操作系统的朋友肯定不陌生,我们可以将某数据源作为下个命令的输入,可以在将下个命令处理过的数据作为下下个命令的输入,这个嵌套使用,可以完成复杂逻辑的业务处理。没错Java中的stream也是这个意思。
🔵流由3个部分组成:
1、数据源:比如集合、文件
2、中间操作:0或多个中间操作,相当于Linux管道流程的嵌套使用
3、终止操作:比如:求平均值、求总和、求最大值
Stream是对LambdaExpression的经典应用,Java8将Stream应用到集合类,提供了大量的工具类,我们可以使用类似于SQL的方式简单、高效的对集合进行操作。
例如:
List<String>names=Arrays.asList(“zhangsan”,“lisi”,“wangwu”);
List.stream().filter(name->name.equals(“zhangsan”))//过滤:相当于SQL的WHERE
.map(String::toUppercase)//相当于SQL的SELECT
.limit(10)//相当于SQL的Limit
.forEach(System.out::println);
从上面的例子看,Java通过Stream与Lambda结合使用,我们是不是可以使用类似于SQL的方式进行操作集合。其实JavaStream还支持分组、求平均值、求最大值等类似SQL的操作。这里不再举出。
Lambda的现状与展望
目前主流编程语言都直接或间接的支持LambdaExpression,例如:Lisp、Python、Ruby、C++、C#、PHP、Java、Kotlin。毕竟LambdaExpression可以简单、高效的实现匿名函数和闭包概念,使程序员可以实现函数式编程。
Java8通过函数式接口间接实现LambdaExpression,弥补了Java中缺失的函数式编程,是Java8新特性中最突出的功能。不但如此Java8还将LambdaExpression和Stream应用到Java的集合类中,使程序员可以像编写SQL语句一样对集合进行串行或并行(Java底层使用Fork/Join框架支持并行对集合操作,这在多核CPU下是更高效的)操作。