1:groupingBy方法分析
public static <T, K, D, A, M extends Map<K, D>>
Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
Supplier<M> mapFactory,
Collector<? super T, A, D> downstream) {
//调用传入的下游收集器,
//产生中间容器进行累加,返回一个A类型的中间容器。
Supplier<A> downstreamSupplier = downstream.supplier();
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
//声明一个新的中间容器累加器,将t作为参数,传入Map<K,A>类型中,Key使用传入一个Function<T>类型的
//分词器,返回一个K类型的数据作为Map的key,而新建A类型作为key的value容器。组合出一个Map<K,A>类
//型的中间容器。
BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
downstreamAccumulator.accept(container, t);
};
//声明一个中间容器的Combine函数。这里我们融合的是Map<K,A>;
BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
//传入一个Supplier<M> 返回一个M类型的Map作为中间容器,而M继承Map<K,D>,
//根据上下文推断,我们之前返回的Map是<K,A>类型的,所以这里可以直接进行强转;
@SuppressWarnings("unchecked")
Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
//判断是否使用finisher函数。
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
}
else {
//声明一个新的finisher,将中间容器转化成M类型。
@SuppressWarnings("unchecked")
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
Function<Map<K, A>, M> finisher = intermediate -> {
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
@SuppressWarnings("unchecked")
M castResult = (M) intermediate;
return castResult;
};
return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
}
}
2:reducing
为什么要使用数组作为承载的容器,因为数字在lambda表达式中是无法传递的,所以需要使用一个容器进行传递。
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 };
}