Lambda表达式
lambda是一个匿名函数,可以吧lambda表达式理解为一段可以传递的代码
lambda表达式基础语法:
java8中引入了一个新的操作符,"->",该操作符称为箭头操作符或者lambda操作符。
箭头两端:
左侧:lambda表达式参数列表
右侧:lambda表达式所需执行的功能,即lambda体。
(1)lambda表达式可以看成接口的实现:即用lambda表达式去实现接口。由于接口中有抽象方法。因此
lambda表达式左侧参数列表:就是接口中抽象方法的参数列表。
lambda表达式右侧就是:需要对这个抽象方法实现的功能。
lambda表达式语法格式:
1、语法格式一:接口中的抽象方法无参数列表,无返回值。
()-> System.out.println(“lambda”);
lambda 操作符左侧用空括号表示,右侧自定义抽象方法的功能。
注意事项:如果在局部内部类中应用了一个同级别的局部变量。
在jdk1.8之前:如果在局部内部类中应用了同级别的局部变量时,该变量必须是final修饰,需要手动加final修饰符,在jdk1.8及以后默认加了final,无需手动添加final修饰符。此时不论是jdk1。7或者jdk1.8以后,在局部内部类中使用同级别的局部变量,该变量相当于常量,因为被final修饰,在局部内部类中不能对该局部变量进行赋值或者操作,该变量相当于常量。
注意在lambda表达式中类似于匿名内部类,在lambda表达式中使用同级别的局部变量时,该变量在jdk1.7前需要手动添加final修饰符,在jdk1.8及以后,无需手动添加final修饰符,默认添加了final修饰符。因此在lambda表达式中使用同级别的局部变量,该变量默认被final修饰,即为常量,不能在lambda表达式中进行重新赋值。
2、语法格式二::有一个参数,并且无返回值
(x) -> System.out.println(x);
lambda表达式左侧接口中抽象方法的参数列表,相当于调用抽象方法,括号中添加参数,不添加类型。
即这里的lambda表达式就是对consumer接口中accept抽象方法的具体实现
3、语法格式三:若只有一个参数,其中小括号()可以省略不写,一般写
**4、语法格式四:**有两个及以上的参数,有返回值,并且 lambda 体中有多条语句
如果lambda体中有多条语句,在lambda体必须使用大括号{}。
(x,y) -> {
System.out.println("");
return Integer.compare(x,y);
}
**5、语法格式五:**如果有两个及以上参数,有返回值,并且lambda表达式中只有一条语句;此时{}和return可以省略
6、语法格式六:lambda表达式的参数列表的数据类型可以省略不写:因为JVM编译器可以通过上下文推断出数据类型。即类型推断。即可以通过接口中抽象方法的参数列列表的数据类型确定当前lambda表达式参数列表的数据类型,即类型推断
总结:
左右遇一括号省;
左侧推断类型省
lambda表达式需要函数式接口的支持
函数式接口: 接口中只有一个抽象方法的接口,称为函数式接口,可以使用注解@FunctionalInterface 修饰,可以检查是否是函数式接口。这个注解放在接口上,对接口进行注解。则这个接口中只能有一个抽象方法,不能有多个抽象方法
而lambda表达式就需要函数式接口的支持
实例
使用lambda表达式实现runnable接口:
@Test
public void test1(){
//使用Java8之前
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("使用Lambda表达式
之前,需要这么写!");
}
}).start();
//使用Lambda表达式
new Thread(() -> System.out.println("使用Lambda
表达式,只需要这一句话!")).start();
}
/**
* 原来使用匿名内部类
*/
public static void test() {
// 使用匿名内部类,重写Intger的 compare方法
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
// 传入比较的方法
TreeSet<Integer> ts = new TreeSet<>(comparator);
}
/**
* 使用Lambda表达式解决匿名内部类需要编写大量模板语言的问题
*/
public static void test2() {
Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
// 传入比较的方法
TreeSet<Integer> ts = new TreeSet<>(comparator);
}