JAVA8学习笔记(四)Collector源码分析与收集器核心

Collector – JavaDoc

  1. 一个可变的规约操作,将输入元素累积到一个可变的输出结果容器中。
  2. 它会在所有元素处理完毕后,将累积的结果转换成为一个最终的表示。(可选操作)
  3. 可以串行/并行。
  4. Collectors本身提供了关于Collector的常见汇聚实现,Collectors本身实际上是一个工厂。
  5. Collector由4个函数构成,
	|---Supplier<A> supplier创建并返回一个新的可变结果容器。
 	|---BiConsumer<A,T> accumulator 将一个新的数据元素合并到结果容器。
 	|---BinaryOperator<T> combiner  并发的
 	|---Function<A,R> finisher 将中间结果转换成最终表示(可选操作)
  1. 串行与并行结果的等价性,得满足以下两个条件
	|--- identity (同一性)a==combiner.apply(a, supplier.get())
 	也就是说(List<T> list1,List<T>list2)->{list1.add(list2);return list1
 	|--- associativity(结合性) 要求r1==r2,文档代码如下
*     A a1 = supplier.get();
 *     accumulator.accept(a1, t1);
 *     accumulator.accept(a1, t2);
 *     R r1 = finisher.apply(a1);  // result without splitting
 *
 *     A a2 = supplier.get();
 *     accumulator.accept(a2, t1);
 *     A a3 = supplier.get();
 *     accumulator.accept(a3, t2);
 *     R r2 = finisher.apply(combiner.apply(a2, a3)); 

关于是否使用Finisher函数
取决于你定义的Collector中的Characteristic中是否有FINISH的enum,当你设置这个enum时,你要确保A->R是成功的。这个强转发生在下图中的调用是否包含FINISH枚举的时候。
而Characteristic的调用是在Stream的实现类
ReferencePipeLine中的collect方法里。
代码如下:

在这里插入图片描述

如图,我们可以看到Collector中声明的三个枚举类的作用。
而并行和串行的调用取决于
在这里插入图片描述

而CONCURRENT这个枚举,在并行流中,代表了多个线程共同调用一个结果容器,则combine方法不需要被调用,如果不包含这个特性,则并行流的每一个线程就都会创建一个结果容器,然后进行combine。

这里可能会在add时报出一个异常
在这里插入图片描述
而这个异常抛出的时机是当你在迭代一个对象时候再修改他。通常这是不允许的。
在这里插入图片描述
同样的,当你使用CONCURRENT枚举时,你的中间容器也只会建立一个。

猜你喜欢

转载自blog.csdn.net/weixin_39781526/article/details/85086239