一、Lambda表达式
Lambda表达式是一种对接口实现的简洁写法
1.1 示例:
在老版本的 Java中是如何排列字符串的:
1 | List<String> list = Arrays.asList("banana","apple", "sun","wall","applet"); |
输出:
[wall, sun, banana, applet, apple]
只需要给静态方法Collections.sort传入一个 List 对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给 sort 方法。
Java 8提供了更简洁的语法,lambda表达式:
1 | Collections.sort(list, (String o1, String o2)-> { |
显然,这样就不用再写传统的匿名对象的方式了,这样代码变得更简短。
这段代码我们还可以写得再简短些:
只有一条return语句,将花括号跟return去掉,如下
1 | Collections.sort(list, (String o1, String o2)-> o2.compareTo(o1)); |
还可以再简短一点:
将数据类型string删掉。
1 | Collections.sort(list, (o1, o2)-> o2.compareTo(o1)); |
1.2 推荐写法:
1 | ([名字1,名字N])->{ |
()和{}都不会省略,是为了提高可读性
只会省略参数类型
1.3 总结:
如果方法体只有一行的情况,那么{}可以省略
注意了如果该行是return语句,那么return关键字也必须省略
如果方法只有一个参数的情况,那么()也可以省略
对于方法的参数类型,要么全部省略要么全部不省略
二、接口的默认方法
Java 8使我们能够通过使用 default关键字向接口添加非抽象方法实现(含方法体的方法)。
重写抽象方法时可直接调用默认方法。
三、函数式接口(Functional Interfaces)
为了解决如何使现有的函数更友好的支持Lambda表达式的问题。
3.1 要求:
接口只有一个抽象方法,但可以有多个非抽象方法;【这种接口一般称为函数式接口】
可以在接口上添加@FunctionalInterface注解来做校验,大于一个抽象方法就会报错。
3.2 示例:
- 当使用多个抽象方法时(接口里的方法public abstract默认省略)
- 正确写法:
3.2 测试:
1 | public static void main(String[] args) { |
测试结果:
3.3 Function源码:
Interface Function<T,R>
参数类型
T - 函数输入的类型
R - 函数的结果类型
- 表示接受一个参数并产生结果的函数。
R apply(T t)方法: 将Function对象应用到输入的参数上,然后返回计算结果。
3.4 内置函数式接口—扩展:
- Predicate 接口是只有一个参数的返回布尔类型值的 断言型 接口。
- Supplier 接口产生给定泛型类型的结果。 与 Function 接口不同,Supplier 接口不接受参数。
- Consumer 接口表示要对单个输入参数执行的操作。
四、Optional
Optional不是函数式接口,而是用于防止 NullPointerException 的工具。
Optional 是一个简单的容器,其值可能是null或者不是null。在Java 8中,你应该返回 Optional 而不是 null。
五、方法引用
可以通过 :: 关键字传递方法或构造函数的引用。
5.1 通过静态方法引用来表示
语法:
1 | 接口类型 名称 = 类名::static方法名 |
案例:
1 | // Function<String, Integer> convert = (String s)-> Integer.valueOf(s); |
5.2 构造方法引用
语法
1 | 接口类型 名称 = 类名::new; //代表引用构造器,至于哪个构造器看接口方法的参数 |
案例:
1 | public class _03TestLambdaConstructorRef { |