lambda 表达式
java 中lambda
表达式 实在 java 8 版本后新加入的特性,Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。 总结语法就是:
1 | (params) -> expression |
使用lambda表达式替换匿名类
以 Runnable 为例
1 | //before java8 |
执行结果是:
1 | before jdk 1.8; |
使用lambda表达式 迭代
以 forEach 为例,迭代所有对象
1 | List<String> list1 = Arrays.asList("spring", "summer", "autumn", "winter"); |
打印结果:
1 | before: spring |
使用lambda表达式和函数式接口Predicate
除了在语言层面支持函数式编程风格,Java 8也添加了一个包,叫做 java.util.function。它包含了很多类,用来支持Java的函数式编程。其中一个便是Predicate,使用 java.util.function.Predicate 函数式接口以及lambda表达式,可以向API方法添加逻辑,用更少的代码支持更多的动态行为。下面是Java 8 Predicate 的例子,展示了过滤集合数据的多种常用方法。Predicate接口非常适用于做过滤。
1 | List<String> list1 = Arrays.asList("spring", "summer", "autumn", "winter"); |
打印结果:
1 | Print which end with n: |
例外 filter 还提供逻辑操作符AND和OR的方法,名字叫做and()、or()和xor(),用于将传入 filter() 方法的条件合并起来。
1 | List<String> list1 = Arrays.asList("spring", "summer", "autumn", "winter"); |
打印结果:
1 | spring |
使用lambda表达式的Map和Reduce
给list 中 每个数据 增加 50%
1 | List<Integer> list2 = Arrays.asList(100, 200, 300, 400); |
打印结果:
1 | 150.0 |
计算一个list 每个值加上 50%后的和
1 | List<Integer> list2 = Arrays.asList(100, 200, 300, 400); |
打印结果:
1 | 1500.0 |
map将集合类(例如列表)元素进行转换的。还有一个 reduce() 函数可以将所有值合并成一个。Map和Reduce操作是函数式编程的核心操作,因为其功能,reduce 又被称为折叠操作。
通过过滤创建一个String列表
通过过滤创建一个新的字符串列表,每个字符串长度大于2
1 | List<String> list3 = Arrays.asList("abc", "def", "hi", "hello"); |
对列表的每个元素应用函数
对list3 的每个元素转换成大写,并用逗号连接起来。
1 | List<String> list3 = Arrays.asList("abc", "def", "hi", "hello"); |
运行结果:
1 | Original List : [abc, def, hi, hello], After String : ABC,DEF,HI,HELLO |
复制不同的值,创建一个子列表
如何利用流的 distinct() 方法来对集合进行去重。
1 | List<Integer> list4 = Arrays.asList(1, 2, 3, 4, 1); |
运行结果:
1 | Original List : [1, 2, 3, 4, 1], Square Reslut : [1, 4, 9, 16] |
计算集合元素的最大值、最小值、总和以及平均值
IntStream、LongStream 和 DoubleStream 等流的类中,有个非常有用的方法叫做 summaryStatistics() 。可以返回 IntSummaryStatistics、LongSummaryStatistics 或者 DoubleSummaryStatistic s,描述流中元素的各种摘要数据。
我们用这个方法来计算列表的最大值和最小值。它也有 getSum() 和 getAverage() 方法来获得列表的所有元素的总和及平均值。
1 | List<Integer> list4 = Arrays.asList(1, 2, 3, 4, 1); |
运行结果:
1 | Highest number in List : 4 |
function 包下的函数式接口
JDK 1.8 API包含了很多内建的函数式接口,在老 Java 中常用到的比如 Comparator
或者 Runnable
接口,这些接口都增加了 @FunctionalInterface
注解以便能用在lambda上。
Java 8 API同样还提供了很多全新的函数式接口来让工作更加方便。
学习例子:
1 | public class Demo { |
总结
- lambda 表达式只能引用
final
或 final 局部变量,这就是说不能在 lambda 内部修改
定义在域外的变量,否则会编译错误。(补充) - Lambda表达式在Java中又称为闭包或匿名函数,
- lambda内部可以使用静态、非静态和局部变量,这称为lambda内的变量捕获。
- 如果在 lambda 表达式 内部不能调用参数方法的引用,需要声明参数类型。
- 合理使用 Function 函数式接口可以方便的构建符合自己的需求的函数。