1、要点概览
- 一个lambda表达式是一个带有参数的代码块
- 当你想要代码块在以后某个时间点执行时,可以使用lambda表达式
- lambda表达式可以被转换为函数式接口
- lambda表达式可以在闭包作用域中有效地访问final变量
- 方法和构造器引用可以引用方法和构造器,但无须调用它们。
- 可以向接口添加默认(default)和静态(static)方法来提供具体的实现。
- 必须解决接口中多个默认方法之间的冲突
2、lambda的几种写法
lambda表达式的格式:参数、箭头->、表达式
1. 指明参数类型,表达式没有大括号
(String a, String b) -> Integer.compare(a.length(), b.length())
2. 指明参数类型,表达式使用大括号
(String a, String b) -> {
if (a.length() < b.length()) return -1;
else if (a.length() > b.length()) return 1;
else return 0;
}
3. 可以没有输入参数
() -> {
for (int i = 0; i < 10; i++) {
doSomething();
}
}
4. 参数类型可以推导得知时,可以省略类型声明;如果只有一个参数,可以省略括号
如下示例,可知list元素类型均为String类型,故可省略类型声明String
List<String> list = Arrays.asList("a", "b", "c");
list.stream().filter((String x) -> StringUtils.isNotBlank(x)).collect(Collectors.toList());
list.stream().filter((x) -> StringUtils.isNotBlank(x)).collect(Collectors.toList());
list.stream().filter(x -> StringUtils.isNotBlank(x)).collect(Collectors.toList());
5. 参数可以添加注解或者final修饰符
(final String x) -> {}
(@NonNull String x) -> {}
3、函数式接口
对于只包含一个抽象方法的接口,可以通过lambda表达式来创建该接口的对象。示例如下:
Arrays.sort(list, (x, y) -> Integer.compare(x.length(), y.length()));
该方法的第二个参数需要一个Comparator接口(该接口只有一个抽象方法)的实例。
可以在任意函数式接口上标注@FunctionalInterface注解,这样做有两个好处。首先,编译器会检查标注该注解的实体,检查该接口是否只包含一个抽象方法。另外,在javadoc页面也会包含一条声明,说明这个接口是一个函数式接口。
当一个lambda表达式被转换为一个函数式接口的实例时,请注意处理检查期异常。
4、方法引用
::操作符将方法名和对象或类的名字分隔开,有三种使用情况
对象::实例方法
类::静态方法
类::实例方法
示例1:
button.setOnAction(System.out::Println);
等同于
button.setOnAction(x -> System.out.println(x));
示例2:
Arrays.sort(arr, String::compareToIgnoreCase);
等同于
Arrays.sort(arr, (x, y) -> x.compareToIgnoreCase(y));
示例3:捕获方法引用中的this参数
this::equals <===> x -> this.equals(x)
在匿名类中,可以调用一个闭合类或父类的员工方法,如 闭合类.this::方法 或者 闭合类.super::方法。
5、构造器引用
labels.stream().map(Button::new).collect(Collectors.toList());
水平有限,后期会继续补充完善。