Lambda表达式
Lamdba 表达式是Java 8 的新特性,也是Java 8 中最重要的的新功能。Lamdaba表达式促进了Java使用函数方式进行编程。
在进行语法的讲解之前,需要了解和Lambda息息相关的Function Interface
,可以说只有函数式接口的存在,才有lambda表达式的存在,换句话可以说lambda表达式是函数式接口的实现.
函数式接口
Function 接口具有单个功能,也就是有单个抽象方法.如 Comparable
接口只有一个方法 compareTo
用来进行比较。
Java8定义了函数接口被用来拓展Lamdba表达式。在 java.util.Function
包下有非常多的函数接口。
常用的接口包括;
接口 | 抽象方法 | 用法 |
---|---|---|
Function<T,R> | R apply(T t); | 接受T类型参数,返回R类型结果 |
Consumer |
void accept(T t); | 接受T类型参数,不返回结果 |
Predicate |
boolean test(T t); | 接受T类型参数,返回Boolean结果 |
Suppler |
T get(); | 无参数,返回T类型结果 |
定义函数接口
- 使用
@FunctionalInterface
注解,该注解不是必须的,但是如果标注,则编译器会检查这个接口下是否只有单个抽象方法,如果不是会报错. - 新增default方法,是为了在现有的类库中中新增功能而不影响他们的实现类
- 新增接口内static方法,可定义一个或者多个静态方法,和普通的静态方法没有区别,都是
接口名.方法名
进行调用 - 在函数式接口的定义中是只允许有且只有一个抽象方法(必须),但是可以有多个static方法和default方法。
Lambda语法
一个Lambda表达式有如下:
1 | paramter -> expression body |
以下是lambda表达式的几个特性
- 可选的类型描述 - 不需要声明参数的类型,编译器可根据参数的值进行推断
- 可选的参数两旁的括号 - 声明单个参数的时候不需要使用括号,但是如何声明多个参数,括号还是必须的。
- 可选的大括号 - 如果函数体中只有单行,则不需要在函数体两侧添加大括号
- 可选的返回值 - 如果函数中只有单行,编译器自动返回这个单行的返回值
下面根据实例来看上面的四个特性:
1 | public class Java8Tester { |
通过上面的例子,可以得出以下重要的两点:
- Lambda 表达式主要用来定义功能接口的内联实现,如:一个接口里只有一个接口方法。在上面的例子里面我们使用了对MathOperation接口进行了多种实现。
- Lambda 表达式消除了对匿名类的需求,如
new Thread(new Runnable{..})
,为Java提供了非常简单而强大的函数编程能力。
使用方法引用
方法引用(Method Refrences)帮助通过方法名称指向方法。方法引用使用符号“::”表示。方法引用可以用爱指向如下类型的方法:
- 静态方法
- 实例方法
- 构造方法使用new关键字(TreeSet::new)
[方法引用]的格式是 类名::方法名
1 | Arrays.stream(objectArray).forEach(System.out::println); |
使用Lambda
熟能生巧,常常练习肯定能记住
1. 创建Thread
1 | // 不使用Lambda创建Thread |
2. 列表迭代
1 |
|
3. Map&Reduce
- 使用Map处理列表内所有元素全部加2
1 | // 不使用Lambda |
- 使用 Map + collect 完成对每个元素计算后返回新的结果列表
1 | List<Integer> newList = new ArrayList<>(); |
4. 使用filter实现元素的过滤
使用lambda,可直接使用filter进行元素的过滤
1 | // 不使用lambda时 |
5. 执行函数
稍复杂的字符串处理,用lambda合适不过了,下面的例子,只将特定字符的字符串进行 toUpperCase
1 | List<String> s = new ArrayList<>(); |
6. 算数运算
支持使用min、max等直接实现Comparator进行运算,如:
1 | Optional<Integer> min = list.stream().min(Integer::compareTo); |
也支持使用 IntSummaryStatistics 状态,如:
1 | IntSummaryStatistics intSummaryStatistics = list.stream().mapToInt(x -> x).summaryStatistics(); |
7. 自定义方法使用Function Inteface实现复杂功能
Java 8 提供了三个常用的函数接口包括;
- Function<T,R>
- Predicate
判断 - Consumer
消费
通过定义方法使用这三类接口,能完成更复杂的调用逻辑,在这里仅仅举一个小例子🌰
1 | List<Integer> functionMethods2(List<Integer> a, Function<List<Integer>, List<Integer>> function) { |