1. Stream.collect()
collect就是一个归约操作,就像reduce一样可以接受各种做法作为参数,将流中的元素累积成一个汇总结果
reduce不会修改累计值对象,而是直接把累计值和当前值做计算操作,产生一个新累计值对象传递下去,而collect每次都会做完操作后修改累计值对象,并把这个累计值对象传递下去,如下图,collect的累计值是一个Container,每次都把当前元素做完操作后,存入Container,并让Container一直往下传递,最后所有的结果都会汇总到Container中
1.3.1 Supplier
用于提供一个累计容器,也就是上图中用于存储元素的Container,通过调用Supplier的get方法得到
1.3.2 Accumulator
用于提供累计函数,即给定累计值和当前值的操作关系
1.3.3 Combiner
用于给定容器合并的规则
Collector就是把collect()方法中需要的函数封装成一个对象
Supplier: 累积数据构造函数
Accumulator: 累积函数,同 reduce
Combiner: 合并函数 ,并行处理场合下用,同 reduce
Finisher: 对 累积数据 做最终 转换
Collectors类就提供了一些api来创建Collector,如我们常用的toList源码如下
可以看出来返回的这个Collector的Supplier是ArrayList::new,accumulator是List::add,combiner是(left, right) -> { left.addAll(right); return left; },没有finisher
把结果归集为一个集合
counting:统计计数
averagingLong/int/Double:求平均
SummarizingDouble/Long/Int
为stream中的元素生成了统计信息,返回的结果是一个统计类
对流中的内元素进行分组
- groupingBy(Function) – 单纯分key存放成Map,默认返回HashMap
- groupingBy(Function, Collector) – 分key后,对每个key的元素进行后续collect操作
- groupingBy(Function, Suppiler, Collector) – 同上,允许通过Suppiler传入其他Map类型
downstream操作:可以嵌套多层Collector,如下,分组完之后还可以传入Collector无限操作
partitioningBy:按条件分成true和false两部分
mapping的功能上和stream.map差不多,但是这个支持downstream,也就是支持映射之后,做进一步操作
reducing:对结果进行归集操作
函数组合就是把多个函数组合成一个函数来执行
先执行andThen前面的函数,再执行后面的函数,相当于数学表达式:f1.andThen(f2) = f2(f1());
先执行后面的函数,再执行前面的函数,相当于数学表达式:f1.compose(f2) = f1(f2());
Optional是java8引入的一个用于解决空指针异常的类,相当于用Optional把对象包装起来,每次都只针对Optional进行操作,这样就能避免空指针异常的出现;
没有Optional之前我们要一层一层判空
有了Optional之后,中间任意一层都可以为空
创建一个空的Optional对象,看源码
不允许传入null对象,否则会报空指针,应该明确对象不为null的时候才使用
允许传入null对象
ofNullable源码可以看到如果传入null,会自动创建一个空的Optional对象
可以取回对象实际值,值为null 的时候抛出异常,所以建议配合下面几个api一起用
if x!= null return x else return T:如果实际值不为空,则返回实际值,否则返回orElse()方法中给定的值
if x!=null return x else return fn:如果值不为空则返回实际值,否则返回函数fn的执行结果
如果实际值为空,则orElse和orElseGet效果差不多,但是如果实际值不为空,虽然都能获取到实际值,但是orElse中的调用还是会执行,而orElseGet的不会执行,所以建议用orElseGet,减少不必要的代码执行,提升性能
if x!= null fn:如果实际值不为空,则执行fn函数
isPresent():判断实际值是否为空
跟stream的map效果差不多也是可以对内容做映射操作
如果一个对象某个成员属性本身是Optional类型的,可能会出现Optional嵌套情况
如果想获取到真实的Pet,需要用flatMap解掉一层Optional
Future接口可以构建异步应用,但依然有其局限性。它很难直接表述多个Future 结果之间的依赖性,CompletableFuture正好可以满足这个要求,如何对两个或多个异步操作进行流水线和合并操作;
由于api非常多,可以通过以下方式来理解api的作用
- accept: 接受参数是 Consumer
- apply: 接受参数是 Function
- handle:接受参数是BiFunction
- runAfter : 接受参数是Runnable
- Either/Both: 任一任务完成还是都完成
- then: 等当前任务完成再执行另一个
- async 后续任务是否异步执行
假如需要完成以下的几个异步调用:
service2依赖于service1的执行结果,service4依赖于service2和service3的执行结果
用传统的Future实现方式:
CompletableFuture实现方式:
Original: https://www.cnblogs.com/jiqirenweb/p/16098702.html
Author: 花好月圆梦
Title: java函数式编程之Collector、Optional、CompletableFuture详解
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/594084/
转载文章受原作者版权保护。转载请注明原作者出处!