背景
要了解流式操作,就必须知道什么是函数式编程及lambda表达式。
java 8 早已经在2014 年 3月 18日发布,毫无疑问 Java 8 对 Java 来说绝对算得上是一次重大版本更新,它包含了十多项语言、库、工具、JVM 等方面的十多项新特性。比如提供了语言级的匿名函数,也就是被官方称为 Lambda 的表达式语法(外界也称为闭包,Lambda 的引入也让流式操作成为可能,减少了代码编写的复杂性),比如函数式接口,方法引用,重复注解。再比如 Optional 预防空指针,Stearm 流式操作,LocalDateTime 时间操作等。
本次我们主要讲解lambda表达式,下节讲解Stearm流式操作
什么lambda表达式
Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)
什么是函数式接口
上面说了本次只讲Lambda表达式,为什么这里又说函数式接口呢?是因为函数接口可以隐式的转为Lambda表达式,在 Java 8中已经有很多接口已经声明为函数接口,如 Runnable、Callable、Comparator 等。
看看java8 中Runable的源码,已经删除了其中的注释
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
那么什么样子的接口才是函数接口呢?有一个很简单的定义,也就是只有一个抽象函数的接口,函数接口使用注解 @FunctionalInterface 进行声明(注解声明不是必须的,如果没有注解,也是只有一个抽象函数,依旧会被认为是函数接口)。多一个或者少一个抽象函数都不能定义为函数接口,如果使用了函数接口注解又不止一个抽象函数,那么编译器会拒绝编译。函数接口在使用时候可以隐式的转换成 Lambda 表达式。
Lmabda语法
好了,进入正题,那什么是Lmabda语法呢
- (params) -> expression
- (params)-> {statements;}
Lambda 的语法特性。
- 使用 ->分割 Lambda 参数和处理语句。
- 类型可选,可以不指定参数类型,编译器可以自动判断。
- 圆括号可选,如果只有一个参数,可以不需要圆括号,多个参数必须要圆括号
- 花括号可选,一个语句可以不用花括号,多个参数则花括号必须。
- 返回值可选,如果只有一个表达式,可以自动返回,不需要 return 语句;花括号中需要 return 语法。
- Lambda 中引用的外部变量必须为 final 类型,内部声明的变量不可修改,内部声明的变量名称不能与外部变量名相同。
params 在只有一个参数或者没有参数的时候,可以直接省略不写
// 1.不需要参数,没有返回值,输出 hello
()->System.out.pritnln("hello");
// 2.不需要参数,返回 hello
()->"hello";
// 3. 接受2个参数(数字),返回两数之和
(x, y) -> x + y
// 4. 接受2个数字参数,返回两数之和
(int x, int y) -> x + y
// 5. 两个数字参数,如果都大于10,返回和,如果都小于10,返回差
(int x,int y) ->{
if( x > 10 && y > 10){
return x + y;
}
if( x < 10 && y < 10){
return Math.abs(x-y);
}
};
通过以上代码,相信大家对Lambda表达式已经有了基本的理解
Lambda表达式使用
对于函数接口
从上面的介绍中已经知道了 Runnable 接口已经是函数接口了,它可以隐式的转换为 Lambda 表达式进行使用,通过下面的创建线程并运行的例子看下 Java 8 中 Lambda 表达式的具体使用方式
/**
* Lambda 的使用,使用 Runnable 例子
* @throws InterruptedException
*/
@Test
public void createLambda() throws InterruptedException {
// 使用 Lambda 之前
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("JDK8 之前的线程创建");
}
};
new Thread(runnable).start();
// 使用 Lambda 之后
Runnable runnable1Jdk8 = (