将行为作为数据传递
函数编程的最直接的表现,莫过于将函数作为数据自由传递,结合泛型推导能力,使代码表达能力获得飞一般的提升。
Java8怎么支持函数式编程? 主要有三个核心概念:
- 函数接口(Function)
- 流(Stream)
- 聚合器(Collector)
函数接口
关于函数接口,两件事:
- 函数接口是行为的抽象
- 函数接口是数据转换器
java.util.Function包,定义了四个最基础的函数接口:
- Supplier
数据转换器,可以提供T类型对象;无参的构造器,提供了get方法
- Function
数据转换器,接收一个T类型的对象,返回一个R类型的对象;单参数单返回值的行为接口;提供了apply,compose,andThen,identity方法;
- Consumer
数据消费器,接收一个T类型的对象,无返回值,通常用于根据T对象做些处理;单参数无返回值的行为接口;提供了accept,andThen方法;
- Predicate
条件测试器,接收一个T类型的对象,返回布尔值,通常用于传递条件函数;单参数布尔值的条件性接口;提供了test(条件测试),and-or-negate(与或非)方法。
其中,compose,andThen,and,or,negate用来组合函数接口而得到更强大的函数接口。
聚合器
每一个流式计算的末尾总有一个类似collect(Collectors.toList())的方法调用。collect是Stream的方法,而参数则是聚合器Collector. 已有的聚合器定义在Collectors的静态方法里。那么这个聚合器怎么实现呢?
Reduce
大部分聚合器都是基于Reduce操作实现的。Reduce, 即推导。含有三个要素:初始值init, 二元操作符BinaryOperator,以及一个用于聚合结果的数据源S.
列表类聚合器
1. 使用ArrayList::new 创建一个空列表;
2.List::add 将Stream累积操作的中间结果加入到这个列表
3. 第三个函数则是将两个列表元素进行合并成一个结果列表中。
实例:集合聚合器toList、toSet 字符串连接器joining(),以及列表求和summingXXX、最多maxBy、最小minby
映射类聚合器
映射类聚合器基于Map合并来完成。
根据指定的值合并函数mergeFunction, 返回一个map合并器,用来合并两个map里相同key的值。mergeFunction用来对两个map中相同key的值进行运算得到新的value值,如果value值为null,会移除相应的key,否则使用value值作为对应key的值。
这个方法私有的,主要为支撑toMap,groupingBy而生。