对于Collectors静态工厂类来说,其实现一共分为两种情况:
Collectors工厂类来说 里面大多是方法都是利用下游收集器的5个方法进行部分改进从而生成一个新的Collector收集器
/*
将流中数据执行mapper映射,映射的数据存到传过来的收集器当中
Set collect = list.stream()
.collect(Collectors.mapping(x -> x + ",", Collectors.toSet()));
//等价上面
list.stream().map(x -> x + ",").collect(Collectors.toList());
System.out.println(collect);
该方法本质是替换参数downstream下游收集器的的accumulator()方法 实现转换返回上游收集器
*/
public static <T, U, A, R>
Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
Collector<? super U, A, R> downstream) {
/*
获取传过来参数的 downstream.accumulator() 行为操作
如 toList方法的List::add
*/
BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
//传过去执行参数的行为操作 (Supplier>) HashSet::new
return new CollectorImpl<>(downstream.supplier(),
//该行为 将流中数据执行mapper.apply(t)的结果存到r(中间容器的)里 (x, y) -> x.add(y);
(r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
//返回并行的函数行为 (left, right) -> { left.addAll(right); return left; },
downstream.combiner(),
//返回收集器参数的finisher行为 x->x
downstream.finisher(),
//CH_UNORDERED_ID
downstream.characteristics());
}
/*
中间转换 将收集器的到数据在进行转换,返回转换后的值
List people
= people.stream().collect(collectingAndThen(toList(),
Collections::unmodifiableList));
*/
public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
Function<R,RR> finisher) {
Set<Collector.Characteristics> characteristics = downstream.characteristics();
/*
为啥去除IDENTITY_FINISH特性?
应为 实例CollectorImpl 必须要调用finisher 如果强制类型转换了
就不会调用finisher
*/
if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {
if (characteristics.size() == 1)
characteristics = Collectors.CH_NOID;
else {
characteristics = EnumSet.copyOf(characteristics);
characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);
characteristics = Collections.unmodifiableSet(characteristics);
}
}
return new CollectorImpl<>(downstream.supplier(),
downstream.accumulator(),
downstream.combiner(),
//改行为是将收集器参数的最终返回值当finisher参数的值出入 返回最终的转换的最终结果
//具体看之前andThen详解
downstream.finisher().andThen(finisher),
characteristics);
}
/*
汇总流中数据 返回收集器
*/
public static <T> Collector<T, ?, Integer>
summingInt(ToIntFunction<? super T> mapper) {
return new CollectorImpl<>(
/中间容器数组
() -> new int[1],
//将流中数据t累加
(a, t) -> {
a[0] += mapper.applyAsInt(t); },
//合并每个数组的值 返回值
(a, b) -> {
a[0] += b[0]; return a; },
//返回最终类型
a -> a[0], CH_NOID);
}
/*
创建收集器
*/
public static <T> Collector<T, ?, T>
reducing(T identity, BinaryOperator<T> op) {
return new CollectorImpl<>(
//生成新的中间容器
boxSupplier(identity),
//数据累加
(a, t) -> {
a[0] = op.apply(a[0], t); },
//并行流收集各线程流的数据
(a, b) -> {
a[0] = op.apply(a[0], b[0]); return a; },
//返回最终的结果
a -> a[0],
//该收集器特性
CH_NOID);
}
@SuppressWarnings("unchecked")
private static <T> Supplier<T[]> boxSupplier(T identity) {
return () -> (T[]) new Object[] {
identity };
}
/*
具体大方向
T:流中元素
K:分类器返回的结果类型(根据谁分组 谁的类型)
D: 被分组的数据类型
A:下游累加器中间结果类型
M:最终返回结果类型
?:表示调用者不关注中间结果生成类型是什么
如 该方法返回的 值M的类型就是 Function
public static <T, K, D, A, M extends Map<K, D>>
Collector<T, ?, M> groupingBy(//key类型
Function<? super T, ? extends K> classifier,
//中间结果类型
Supplier<M> mapFactory,
//下游收集器
Collector<? super T, A, D> downstream) {
//获取下游收集器的supplier方法 (Supplier>) ArrayList::new生成中间容器
Supplier<A> downstreamSupplier = downstream.supplier();
// 获取下游收集器的accumulator方法 List::add得到累加器对象
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
//将classifier行为执行结果做key 中间容器结果做value 封装成map生成中间累加器对象
//将流中数据填充到A当中
BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
//将流中元素执行classifier行为得到的结果做key
K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
//computeIfAbsent方法返回指定的键应key的容器对象(方法详解如下)
/*如果m map中key没有对应值会将 key和 downstreamSupplier.get()
得到的结果组合put到m(Map m) map当中
此时就生成一个新的BiConsumer
A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
/*
将流中数据累加到新的BiConsumer
downstreamAccumulator.accept(container, t);
};
//并行合并多线程执行结果得到最终返回结果数据 该行为作为上游收集器的combiner()行为
BinaryOperator<Map<K, A>> merger = Collectors., A, Map<K, A>>mapMerger(downstream.combiner());
/*
将传过来的HashMap::new得到的中间结果类型强转成 上游需要的中间结果容器
mapFactory.get方法肯定返回此时中间结果类型
此时上下文已经定义好了中间结果类型所以能强转成功
*/
@SuppressWarnings("unchecked")
Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
//根据特性分别实现收集器 如果设置了IDENTITY_FINISH 无需给定finisher
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
}
else {
//反之
@SuppressWarnings("unchecked")
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
Function<Map<K, A>, M> finisher = intermediate -> {
//通过map.replaceAll方法执行downstreamFinisher.apply行为
//得到的结果替换到该key的value值当中
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
@SuppressWarnings("unchecked")//强转成返回结果
M castResult = (M) intermediate;
return castResult;
};
return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
}
}
public static <T, D, A>
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
Collector<? super T, A, D> downstream) {
//获取下游的accumulator() 如toLIst的List::add
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
//通过行为判断将流中元素分别存到Partition的forTrue或forFalse当中
//此时Partition默认设置为k v的形式
BiConsumer<Partition<A>, T> accumulator = (result, t) ->
downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);
//多线程合并线程的数据
BinaryOperator<A> op = downstream.combiner();
BinaryOperator<Partition<A>> merger = (left, right) ->
new Partition<>(op.apply(left.forTrue, right.forTrue),
op.apply(left.forFalse, right.forFalse));
Supplier<Partition<A>> supplier = () ->
new Partition<>(downstream.supplier().get(),
downstream.supplier().get());
//如果IDENTITY_FINISH特性 中间和最终结果容器相同直接返回
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
}
else {
Function<Partition<A>, Map<Boolean, D>> finisher = par ->
//Partition 最终返回类型就是 Map 类型
new Partition<>(downstream.finisher().apply(par.forTrue),
downstream.finisher().apply(par.forFalse));
return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
}
}