Collectors

Collectors 配合 stream 可以实现 MapReduce 操作,也可以单独完成流中元素的收集。

收集器接口和实现

/**
* 收集器接口
*/
public interface Collector<T, A, R> {
/**
* 创建并返回一个可变的结果容器
*/
Supplier<A> supplier(); /**
* 创建并返回一个将值归约到可变结果容器中的累加器
*/
BiConsumer<A, T> accumulator(); /**
* 创建并返回一个将两个结果容器进行合并的组合器,适用于并行计算
*/
BinaryOperator<A> combiner(); /**
* 创建并返回一个将结果容器转换为最终输出的完成器
*/
Function<A, R> finisher(); /**
* 此收集器所持有的 Collector.Characteristics 特征集
*/
Set<Characteristics> characteristics(); /**
* 用于优化归约操作的收集器特征值
*/
enum Characteristics {
/**
* 结果容器支持并发处理
*/
CONCURRENT, /**
* 收集器处理元素时是无序的
*/
UNORDERED, /**
* 结果容器就是最终返回的结果,不需要执行完成器操作
*/
IDENTITY_FINISH
}
} /**
* Collector 接口的简单实现
*/
static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
private final Supplier<A> supplier;
private final BiConsumer<A, T> accumulator;
private final BinaryOperator<A> combiner;
private final Function<A, R> finisher;
private final Set<Characteristics> characteristics; CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A,R> finisher,
Set<Characteristics> characteristics) {
this.supplier = supplier;
this.accumulator = accumulator;
this.combiner = combiner;
this.finisher = finisher;
this.characteristics = characteristics;
} CollectorImpl(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Set<Characteristics> characteristics) {
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
} @Override
public BiConsumer<A, T> accumulator() {
return accumulator;
} @Override
public Supplier<A> supplier() {
return supplier;
} @Override
public BinaryOperator<A> combiner() {
return combiner;
} @Override
public Function<A, R> finisher() {
return finisher;
} @Override
public Set<Characteristics> characteristics() {
return characteristics;
}
}

简单的结果收集

  • toList():将流中的元素收集到一个 ArrayList 中
    /**
* 将流中的元素收集到一个 ArrayList 中
*/
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
} ReferencePipeline#
@Override
@SuppressWarnings("unchecked")
public final <R, A> R collect(Collector<? super P_OUT, A, R> collector) {
A container;
// 1)如果是并行收集 && 收集器的结果容器支持并发处理 && 元素是无序的
if (isParallel()
&& collector.characteristics().contains(Collector.Characteristics.CONCURRENT)
&& (!isOrdered() || collector.characteristics().contains(Collector.Characteristics.UNORDERED))) {
// 通过共享的结果容器完成收集
container = collector.supplier().get();
final BiConsumer<A, ? super P_OUT> accumulator = collector.accumulator();
forEach(u -> accumulator.accept(container, u));
}
// 2)收集过程是串行的 || 并行处理的收集器结果容器不支持并发
else {
// 执行收集过程,并返回结果容器
container = evaluate(ReduceOps.makeRef(collector));
}
/**
* 1)如果是 IDENTITY_FINISH,则直接返回结果容器
* 2)否则执行合并操作
*/
return collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)
? (R) container
: collector.finisher().apply(container);
} ReduceOps#
/**
* 创建一个用于归约引用对象的终端收集操作
*/
public static <T, I> TerminalOp<T, I>
makeRef(Collector<? super T, I, ?> collector) {
// 获取结果容器的生成器
final Supplier<I> supplier = Objects.requireNonNull(collector).supplier();
// 获取累加器的生成器
final BiConsumer<I, ? super T> accumulator = collector.accumulator();
// 获取合并器的生成器
final BinaryOperator<I> combiner = collector.combiner();
// 定义 ReducingSink
class ReducingSink extends Box<I>
implements AccumulatingSink<T, I, ReducingSink> {
@Override
public void begin(long size) {
// 生成结果容器并写入 state
state = supplier.get();
} @Override
public void accept(T t) {
// 使用累加器进行归约
accumulator.accept(state, t);
} @Override
public void combine(ReducingSink other) {
// 使用合并器进行两个结果容器的合并
state = combiner.apply(state, other.state);
}
}
return new ReduceOp<T, I, ReducingSink>(StreamShape.REFERENCE) {
@Override
public ReducingSink makeSink() {
return new ReducingSink();
} @Override
public int getOpFlags() {
return collector.characteristics().contains(Collector.Characteristics.UNORDERED)
? StreamOpFlag.NOT_ORDERED
: 0;
}
};
} /**
* 用于执行 reduce 操作的终端 sink
*/
private interface AccumulatingSink<T, R, K extends AccumulatingSink<T, R, K>>
extends TerminalSink<T, R> {
void combine(K other);
} /**
* 用于保存单个结果值的容器
*/
private abstract static class Box<U> {
/**
* 结果值
*/
U state; Box() {} // Avoid creation of special accessor public U get() {
return state;
}
} /**
* 一个终端归约操作,用于评估流水线中产生的每个元素,并将其发送到收集器中
*/
private abstract static class ReduceOp<T, R, S extends AccumulatingSink<T, R, S>>
implements TerminalOp<T, R> {
/**
* 输入元素类型
*/
private final StreamShape inputShape; ReduceOp(StreamShape shape) {
inputShape = shape;
} /**
* 创建 sink
*/
public abstract S makeSink(); @Override
public StreamShape inputShape() {
return inputShape;
} /**
* 串行处理流水线中生成的元素
*/
@Override
public <P_IN> R evaluateSequential(PipelineHelper<T> helper,
Spliterator<P_IN> spliterator) {
return helper.wrapAndCopyInto(makeSink(), spliterator).get();
} /**
* 并行处理流水线中生成的元素
*/
@Override
public <P_IN> R evaluateParallel(PipelineHelper<T> helper,
Spliterator<P_IN> spliterator) {
return new ReduceTask<>(this, helper, spliterator).invoke().get();
}
} /**
* A {@code ForkJoinTask} for performing a parallel reduce operation.
*/
@SuppressWarnings("serial")
private static final class ReduceTask<P_IN, P_OUT, R,
S extends AccumulatingSink<P_OUT, R, S>>
extends AbstractTask<P_IN, P_OUT, S, ReduceTask<P_IN, P_OUT, R, S>> {
/**
* 终端归约操作
*/
private final ReduceOp<P_OUT, R, S> op; ReduceTask(ReduceOp<P_OUT, R, S> op,
PipelineHelper<P_OUT> helper,
Spliterator<P_IN> spliterator) {
super(helper, spliterator);
this.op = op;
} ReduceTask(ReduceTask<P_IN, P_OUT, R, S> parent,
Spliterator<P_IN> spliterator) {
super(parent, spliterator);
this.op = parent.op;
} /**
* 创建一个子任务
*/
@Override
protected ReduceTask<P_IN, P_OUT, R, S> makeChild(Spliterator<P_IN> spliterator) {
return new ReduceTask<>(this, spliterator);
} /**
* 执行此叶子任务的元素收集
*/
@Override
protected S doLeaf() {
return helper.wrapAndCopyInto(op.makeSink(), spliterator);
} @Override
public void onCompletion(CountedCompleter<?> caller) {
// 如果不是叶子任务,则需要合并两个子节点的结果
if (!isLeaf()) {
// 读取左子节点的任务执行结果
S leftResult = leftChild.getLocalResult();
// 读取右子节点的任务执行结果,并使用合并器进行累加
leftResult.combine(rightChild.getLocalResult());
// 写入结果到当前任务中
setLocalResult(leftResult);
}
// GC spliterator, left and right child
super.onCompletion(caller);
}
}
  • toCollection():将流中的元素收集到一个 Collection 中
    /**
* 将流中的元素收集到一个 Collection 中
*/
public static <T, C extends Collection<T>>
Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
return new CollectorImpl<>(collectionFactory, Collection<T>::add,
(r1, r2) -> { r1.addAll(r2); return r1; },
CH_ID);
}
  • toSet():将流中的元素收集到一个 HashSet 中
    /**
* 将流中的元素收集到一个 HashSet 中
*/
public static <T>
Collector<T, ?, Set<T>> toSet() {
return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
(left, right) -> {
// 根据结果容器的大小,优化合并过程
if (left.size() < right.size()) {
right.addAll(left); return right;
} else {
left.addAll(right); return left;
}
},
CH_UNORDERED_ID);
}
  • toMap():将流中的元素收集到一个 map 中,键不能重复、值不能为 null。如果键出现重复,则抛出 IllegalStateException 异常
    /**
* 将流中的元素收集到一个 map 中,如果键出现重复,则抛出 IllegalStateException 异常。
*
* @param <T> 输入元素类型
* @param <K> 键元素类型
* @param <U> 值元素类型
* @param keyMapper 基于输入元素生成键
* @param valueMapper 基于输入元素生成值
*/
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return new CollectorImpl<>(HashMap::new,
uniqKeysMapAccumulator(keyMapper, valueMapper),
uniqKeysMapMerger(),
CH_ID);
} private static <T, K, V>
BiConsumer<Map<K, V>, T> uniqKeysMapAccumulator(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper) {
return (map, element) -> {
// 生成键
final K k = keyMapper.apply(element);
// 生成值,值不能为 null
final V v = Objects.requireNonNull(valueMapper.apply(element));
// 如果键已经存在,则抛出 IllegalStateException 异常
final V u = map.putIfAbsent(k, v);
if (u != null) {
throw duplicateKeyException(k, u, v);
}
};
} /**
* 将两个 map 中的键值对进行合并【考虑计算 size 进行优化处理】。
* 键出现重复,则抛出 IllegalStateException 异常
*/
private static <K, V, M extends Map<K,V>>
BinaryOperator<M> uniqKeysMapMerger() {
return (m1, m2) -> {
for (final Map.Entry<K,V> e : m2.entrySet()) {
final K k = e.getKey();
final V v = Objects.requireNonNull(e.getValue());
final V u = m1.putIfAbsent(k, v);
if (u != null) {
throw duplicateKeyException(k, u, v);
}
}
return m1;
};
}
  • toMap():将流中的元素收集到一个 map 中,合并时执行 megre 操作【键冲突不会跑异常】
    /**
* 将流中的元素收集到一个 map 中,合并时执行 megre 操作【键冲突不会跑异常】
*/
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction) {
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
} public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapFactory) {
// 使用 merge 函数进行归约
final BiConsumer<M, T> accumulator
= (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_ID);
} /**
* 将右侧的 map 合并进左侧的 map,键冲突时使用 merge 函数进行处理
*/
private static <K, V, M extends Map<K,V>>
BinaryOperator<M> mapMerger(BinaryOperator<V> mergeFunction) {
return (m1, m2) -> {
for (final Map.Entry<K,V> e : m2.entrySet()) {
m1.merge(e.getKey(), e.getValue(), mergeFunction);
}
return m1;
};
}
  • toConcurrentMap:将流中的元素收集到一个 ConcurrentHashMap 中,键和值都不能为 null,键不能重复。
    /**
* 将流中的元素收集到一个 ConcurrentHashMap 中
*/
public static <T, K, U>
Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return new CollectorImpl<>(ConcurrentHashMap::new,
uniqKeysMapAccumulator(keyMapper, valueMapper),
uniqKeysMapMerger(),
CH_CONCURRENT_ID);
}
  • toUnmodifiableList():将流中的元素收集到一个不可变的 List 中
    /**
* 将流中的元素收集到一个不可变的 List 中
* @since 10
*/
@SuppressWarnings("unchecked")
public static <T>
Collector<T, ?, List<T>> toUnmodifiableList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
list -> (List<T>)List.of(list.toArray()),
CH_NOID);
}
  • toUnmodifiableSet():将流中的元素收集到一个不可变的 set 中
    /**
* 将流中的元素收集到一个不可变的 set 中
* @since 10
*/
@SuppressWarnings("unchecked")
public static <T>
Collector<T, ?, Set<T>> toUnmodifiableSet() {
return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
(left, right) -> {
if (left.size() < right.size()) {
right.addAll(left); return right;
} else {
left.addAll(right); return left;
}
},
set -> (Set<T>)Set.of(set.toArray()),
CH_UNORDERED_NOID);
}
  • toUnmodifiableMap():将流中的元素收集到一个不可变的 Map 中
    /**
* 将流中的元素收集到一个不可变的 Map 中
* @since 10
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static <T, K, U>
Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
Objects.requireNonNull(keyMapper, "keyMapper");
Objects.requireNonNull(valueMapper, "valueMapper");
return collectingAndThen(
toMap(keyMapper, valueMapper),
map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
}

自定义归约

  • reducing():使用 BinaryOperator 对流中的元素进行归约,返回一个 Optional 对象,未指定初始值。
    /**
* 使用 BinaryOperator 对流中的元素进行归约,返回一个 Optional 对象
*/
public static <T> Collector<T, ?, Optional<T>>
reducing(BinaryOperator<T> op) {
class OptionalBox implements Consumer<T> {
/**
* 结果值
*/
T value = null;
/**
* 是否已经有结果值
*/
boolean present = false; @Override
public void accept(T t) {
// 1)如果已经有结果值,则执行归约
if (present) {
value = op.apply(value, t);
}
// 2)第一个元素,则直接写入结果值中
else {
value = t;
present = true;
}
}
} return new CollectorImpl<>(
OptionalBox::new, OptionalBox::accept,
(a, b) -> { if (b.present) {
a.accept(b.value);
} return a; },
a -> Optional.ofNullable(a.value), CH_NOID);
}
  • 使用 BinaryOperator 对流中的元素进行归约,指定初始值为 identity。
    /**
*/
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 };
}
  • 使用 BinaryOperator 对流中的元素进行归约,归约前先使用 mapper 进行映射处理,指定初始值为 identity。
    /**
*/
public static <T, U>
Collector<T, ?, U> reducing(U identity,
Function<? super T, ? extends U> mapper,
BinaryOperator<U> op) {
return new CollectorImpl<>(
boxSupplier(identity),
// 先使用 mapper 进行映射,然后再归约
(a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); },
(a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
a -> a[0], CH_NOID);
}

统计

  • averagingInt():先将流中的元素转换为 int 值,然后统计平均值
    /**
* 先将流中的元素转换为 int 值,然后统计平均值
*/
public static <T> Collector<T, ?, Double>
averagingInt(ToIntFunction<? super T> mapper) {
return new CollectorImpl<>(
() -> new long[2],
// 第一个 slot 记录总和,第二个 slot 记录总个数
(a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
a -> a[1] == 0 ? 0.0d : (double) a[0] / a[1], CH_NOID);
}
  • averagingLong():先将流中的元素转换为 long 值,然后统计平均值
    /**
* 先将流中的元素转换为 long 值,然后统计平均值
*/
public static <T> Collector<T, ?, Double>
averagingLong(ToLongFunction<? super T> mapper) {
return new CollectorImpl<>(
() -> new long[2],
// 第一个 slot 记录总和,第二个 slot 记录总个数
(a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
a -> a[1] == 0 ? 0.0d : (double) a[0] / a[1], CH_NOID);
}
  • averagingDouble():先将流中的元素转换为 double 值,然后统计平均值
    /**
* 先将流中的元素转换为 double 值,然后统计平均值
*/
public static <T> Collector<T, ?, Double>
averagingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the number of values seen.
*/
return new CollectorImpl<>(
() -> new double[4],
(a, t) -> { final double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3]+= val;},
(a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
a -> a[2] == 0 ? 0.0d : computeFinalSum(a) / a[2],
CH_NOID);
}
  • summingInt():先将流中的元素转换为 int 值,然后统计总和
    /**
* 先将流中的元素转换为 int 值,然后统计总和
*/
public static <T> Collector<T, ?, Integer>
summingInt(ToIntFunction<? super T> mapper) {
return new CollectorImpl<>(
() -> new int[1],
(a, t) -> { a[0] += mapper.applyAsInt(t); },
(a, b) -> { a[0] += b[0]; return a; },
a -> a[0], CH_NOID);
}
  • summingLong():先将流中的元素转换为 long 值,然后统计总和
    /**
* 先将流中的元素转换为 long 值,然后统计总和
*/
public static <T> Collector<T, ?, Long>
summingLong(ToLongFunction<? super T> mapper) {
return new CollectorImpl<>(
() -> new long[1],
(a, t) -> { a[0] += mapper.applyAsLong(t); },
(a, b) -> { a[0] += b[0]; return a; },
a -> a[0], CH_NOID);
}
  • summingDouble():先将流中的元素转换为 double 值,然后统计总和
    /**
* 先将流中的元素转换为 double 值,然后统计总和
*/
public static <T> Collector<T, ?, Double>
summingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the simple sum used to compute
* the proper result if the stream contains infinite values of
* the same sign.
*/
return new CollectorImpl<>(
() -> new double[3],
(a, t) -> { final double val = mapper.applyAsDouble(t);
sumWithCompensation(a, val);
a[2] += val;},
(a, b) -> { sumWithCompensation(a, b[0]);
a[2] += b[2];
return sumWithCompensation(a, b[1]); },
a -> computeFinalSum(a),
CH_NOID);
}
  • summarizingInt():先将流中的元素转换为 int 值,然后统计到 IntSummaryStatistics【合并了 count、sum、min、max、avg】 中。
    /**
* 先将流中的元素转换为 int 值,然后统计到 IntSummaryStatistics【合并了 count、sum、min、max、avg】 中。
*/
public static <T>
Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) {
return new CollectorImpl<>(
IntSummaryStatistics::new,
(r, t) -> r.accept(mapper.applyAsInt(t)),
(l, r) -> { l.combine(r); return l; }, CH_ID);
}
  • summarizingLong():先将流中的元素转换为 long 值,然后统计到 LongSummaryStatistics【合并了 count、sum、min、max、avg】 中。
    /**
* 先将流中的元素转换为 long 值,然后统计到 LongSummaryStatistics【合并了 count、sum、min、max、avg】 中。
*/
public static <T>
Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) {
return new CollectorImpl<>(
LongSummaryStatistics::new,
(r, t) -> r.accept(mapper.applyAsLong(t)),
(l, r) -> { l.combine(r); return l; }, CH_ID);
}
  • summarizingDouble():先将流中的元素转换为 double 值,然后统计到 DoubleSummaryStatistics【合并了 count、sum、min、max、avg】 中。
    /**
* 先将流中的元素转换为 double 值,然后统计到 DoubleSummaryStatistics【合并了 count、sum、min、max、avg】 中。
*/
public static <T>
Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) {
return new CollectorImpl<>(
DoubleSummaryStatistics::new,
(r, t) -> r.accept(mapper.applyAsDouble(t)),
(l, r) -> { l.combine(r); return l; }, CH_ID);
}
  • counting():统计流中的总元素数
    /**
* 统计流中的总元素数
*/
public static <T> Collector<T, ?, Long>
counting() {
return summingLong(e -> 1L);
}
- minBy():读取流中的最小值
```java
/**
* 读取流中的最小值
*/
public static <T> Collector<T, ?, Optional<T>>
minBy(Comparator<? super T> comparator) {
return reducing(BinaryOperator.minBy(comparator));
}
  • maxBy():读取流中的最大值
    /**
* 读取流中的最大值
*/
public static <T> Collector<T, ?, Optional<T>>
maxBy(Comparator<? super T> comparator) {
return reducing(BinaryOperator.maxBy(comparator));
}

分组

  • groupingBy【串行分组】
    /**
* 使用指定的分类器 classifier 将流中的元素进行分组,同一个组中的元素被收集到一个 ArrayList 中。
*/
public static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
} /**
* 使用指定的分类器 classifier 将流中的元素进行分组,同一个组中的元素被收集到一个 downstream 收集器中。
*/
public static <T, K, A, D>
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
Collector<? super T, A, D> downstream) {
return groupingBy(classifier, HashMap::new, downstream);
} /**
* 使用指定的分类器 classifier 将流中的元素进行分组,同一个组中的元素被收集到一个 downstream 收集器中。
*/
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) {
// 同一组元素的结果容器
final Supplier<A> downstreamSupplier = downstream.supplier();
// 同一组元素的累加器
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
// 分组累加器
final BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
// 计算分组键
final K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
// 读取分组容器
final A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
// 执行归约
downstreamAccumulator.accept(container, t);
};
// 并行分组的合并器
final BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
// 结果容器的生成器
final Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
// 1)无序合并处理
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
}
// 2)执行合并处理
else {
@SuppressWarnings("unchecked")
final
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
final Function<Map<K, A>, M> finisher = intermediate -> {
// 对所有的分组执行最后的映射
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
@SuppressWarnings("unchecked")
final
M castResult = (M) intermediate;
return castResult;
};
return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
}
}
  • groupingByConcurrent【并行分组】
    /**
* 【并行分组】使用指定的分类器 classifier 将流中的元素进行分组,同一个组中的元素被收集到一个 ArrayList 中。
*/
public static <T, K>
Collector<T, ?, ConcurrentMap<K, List<T>>>
groupingByConcurrent(Function<? super T, ? extends K> classifier) {
return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
} /**
* 【并行分组】使用指定的分类器 classifier 将流中的元素进行分组,同一个组中的元素被收集到一个 downstream 收集器中。
*/
public static <T, K, A, D>
Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier,
Collector<? super T, A, D> downstream) {
return groupingByConcurrent(classifier, ConcurrentHashMap::new, downstream);
} /**
* 【并行分组】使用指定的分类器 classifier 将流中的元素进行分组,同一个组中的元素被收集到一个 downstream 收集器中。
*/
public static <T, K, A, D, M extends ConcurrentMap<K, D>>
Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier,
Supplier<M> mapFactory,
Collector<? super T, A, D> downstream) {
final Supplier<A> downstreamSupplier = downstream.supplier();
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
final BinaryOperator<ConcurrentMap<K, A>> merger = Collectors.<K, A, ConcurrentMap<K, A>>mapMerger(downstream.combiner());
@SuppressWarnings("unchecked")
final
Supplier<ConcurrentMap<K, A>> mangledFactory = (Supplier<ConcurrentMap<K, A>>) mapFactory;
BiConsumer<ConcurrentMap<K, A>, T> accumulator;
// 同一个分组的结果容器是线程安全的
if (downstream.characteristics().contains(Collector.Characteristics.CONCURRENT)) {
accumulator = (m, t) -> {
final K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
final A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
downstreamAccumulator.accept(resultContainer, t);
};
}
// 同一个分组的结果容器是不是线程安全的,则使用 synchronized 实现同步
else {
accumulator = (m, t) -> {
final K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
final A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
synchronized (resultContainer) {
downstreamAccumulator.accept(resultContainer, t);
}
};
} if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_CONCURRENT_ID);
}
else {
@SuppressWarnings("unchecked")
final
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
final Function<ConcurrentMap<K, A>, M> finisher = intermediate -> {
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
@SuppressWarnings("unchecked")
final
M castResult = (M) intermediate;
return castResult;
};
return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID);
}
}
  • partitioningBy【分区】
    /**
* 使用指定的断言 predicate 对流中的元素进行二分,
* 断言结果为 true 的所有元素同一个组,断言结果为 false 的所有元素同一个组,
* 同一个组中的元素收集到一个 ArrayList 中。
*/
public static <T>
Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
return partitioningBy(predicate, toList());
} /**
* 使用指定的断言 predicate 对流中的元素进行二分,
* 断言结果为 true 的所有元素同一个组,断言结果为 false 的所有元素同一个组,
* 使用指定的收集器来收集同一个组中的元素。
*/
public static <T, D, A>
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
Collector<? super T, A, D> downstream) {
// 同一组的累加器
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
// 流的累加器
final BiConsumer<Partition<A>, T> accumulator = (result, t) ->
downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);
// 同一组的合并器
final BinaryOperator<A> op = downstream.combiner();
// 流的合并器
final BinaryOperator<Partition<A>> merger = (left, right) ->
new Partition<>(op.apply(left.forTrue, right.forTrue),
op.apply(left.forFalse, right.forFalse));
// 结果容器生成器
final Supplier<Partition<A>> supplier = () ->
new Partition<>(downstream.supplier().get(),
downstream.supplier().get());
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
}
else {
final Function<Partition<A>, Map<Boolean, D>> finisher = par ->
new Partition<>(downstream.finisher().apply(par.forTrue),
downstream.finisher().apply(par.forFalse));
return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
}
}

其他

  • filtering():先对流中的元素执行过滤,满足断言的再执行收集。
    /**
* 先对流中的元素执行过滤,满足断言的再执行收集。
* @since 9
*/
public static <T, A, R>
Collector<T, ?, R> filtering(Predicate<? super T> predicate,
Collector<? super T, A, R> downstream) {
final BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
return new CollectorImpl<>(downstream.supplier(),
(r, t) -> {
if (predicate.test(t)) {
downstreamAccumulator.accept(r, t);
}
},
downstream.combiner(), downstream.finisher(),
downstream.characteristics());
}
  • mapping():先对流中的元素执行映射,然后再执行收集。
    /**
* 先对流中的元素执行映射,然后再执行收集。
*/
public static <T, U, A, R>
Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
Collector<? super U, A, R> downstream) {
final BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
return new CollectorImpl<>(downstream.supplier(),
(r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
downstream.combiner(), downstream.finisher(),
downstream.characteristics());
}
  • flatMapping():通过流中的每一个元素生成一个子流,然后再对子流中的元素执行收集
    /**
* 通过流中的每一个元素生成一个子流,然后再对子流中的元素执行收集
* @since 9
*/
public static <T, U, A, R>
Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
Collector<? super U, A, R> downstream) {
final BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
return new CollectorImpl<>(downstream.supplier(),
(r, t) -> {
try (Stream<? extends U> result = mapper.apply(t)) {
if (result != null) {
result.sequential().forEach(u -> downstreamAccumulator.accept(r, u));
}
}
},
downstream.combiner(), downstream.finisher(),
downstream.characteristics());
}
  • joining():字符序列流的拼接
    /**
* 对元素类型为 String 的流中的每一个元素执行拼接
*/
public static Collector<CharSequence, ?, String> joining() {
return new CollectorImpl<>(
StringBuilder::new, StringBuilder::append,
(r1, r2) -> { r1.append(r2); return r1; },
StringBuilder::toString, CH_NOID);
} /**
* 对元素类型为 String 的流中的每一个元素执行拼接,指定分割符为 delimiter
*/
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
return joining(delimiter, "", "");
} /**
* 对元素类型为 String 的流中的每一个元素执行拼接,指定分割符为 delimiter,结果前缀为 prefix,结果后缀为 suffix
*/
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
return new CollectorImpl<>(
() -> new StringJoiner(delimiter, prefix, suffix),
StringJoiner::add, StringJoiner::merge,
StringJoiner::toString, CH_NOID);
}

Collector 源码分析的更多相关文章

  1. java8学习之Collector源码分析与收集器核心

    之前已经对流在使用上已经进行了大量应用了,也就是说对于它的应用是比较熟悉了,但是比较欠缺的是对于它底层的实现还不太了解,所以接下来准备大量通过阅读官方的javadoc反过来加深对咱们已经掌握这些知识更 ...

  2. spring源码分析之spring-core总结篇

    1.spring-core概览 spring-core是spring框架的基石,它为spring框架提供了基础的支持. spring-core从源码上看,分为6个package,分别是asm,cgli ...

  3. Solr4.8.0源码分析(6)之非排序查询

    Solr4.8.0源码分析(6)之非排序查询 上篇文章简单介绍了Solr的查询流程,本文开始将详细介绍下查询的细节.查询主要分为排序查询和非排序查询,由于两者走的是两个分支,所以本文先介绍下非排序的查 ...

  4. Solr4.8.0源码分析(5)之查询流程分析总述

    Solr4.8.0源码分析(5)之查询流程分析总述 前面已经写到,solr查询是通过http发送命令,solr servlet接受并进行处理.所以solr的查询流程从SolrDispatchsFilt ...

  5. Mahout源码分析:并行化FP-Growth算法

    FP-Growth是一种常被用来进行关联分析,挖掘频繁项的算法.与Aprior算法相比,FP-Growth算法采用前缀树的形式来表征数据,减少了扫描事务数据库的次数,通过递归地生成条件FP-tree来 ...

  6. Java并发编程之ThreadLocal源码分析

    ## 1 一句话概括ThreadLocal<font face="微软雅黑" size=4>  什么是ThreadLocal?顾名思义:线程本地变量,它为每个使用该对象 ...

  7. JUnit源码分析 - 扩展 - 自定义Rule

    JUnit Rule简述 Rule是JUnit 4.7之后新加入的特性,有点类似于拦截器,可以在测试类或测试方法执行前后添加额外的处理,本质上是对@BeforeClass, @AfterClass, ...

  8. JVM源码分析之SystemGC完全解读

    JVM源码分析之SystemGC完全解读 概述 JVM的GC一般情况下是JVM本身根据一定的条件触发的,不过我们还是可以做一些人为的触发,比如通过jvmti做强制GC,通过System.gc触发,还可 ...

  9. nGrinder对监控机器收集自定义数据及源码分析

    转载:https://blog.csdn.net/neven7/article/details/50782451 0.背景 性能测试工具nGrinder支持在无需修改源码的情况下,对目标服务器收集自定 ...

随机推荐

  1. linux的mv、cp 命令

    用mv命令1.作用mv命令来为文件或目录改名或将文件由一个目录移入另一个目录中.该命令等同于DOS系统下的ren和move命令的组合.它的使用权限是所有用户.2.格式mv [options] 源文件或 ...

  2. PHP 中一个 False 引发的问题,差点让公司损失一百万

    PHP 中一个 False 引发的问题,差点让公司损失一百万 一.场景描述 上周我一个在金融公司的同学,他在线上写一个 Bug,差点造成公司损失百万.幸好他及时发现了这个问题并修复了.这是一个由 PH ...

  3. 剑指offer-二维数组中的查找-数组-python

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  4. Windows 环境下安装redis 及其PHP Redis扩展

    1.安装Redis (1)这里选择在github官网上下载Redis,地址:Redis下载地址 下载压缩包(如下图),并解压到本地目录,我放在D:\redis (2)验证Redis安装是否成功打开命令 ...

  5. Spark Streaming整合Flume + Kafka wordCount

    flume配置文件 flume_to_kafka.conf a1.sources = r1 a1.sinks = k1 a1.channels = c1 a1.sources.r1.type = sp ...

  6. scala学习笔记(7)

    1.包 --------------------------------------- Scala中的包和Java或者C++中命名空间的目的是相同的:管理大型程序中的名称. package a{ pa ...

  7. js放大镜特效

    在平时网上商城购物时,我们能够通过放大镜效果来使我们看图片能够更加的清楚,今天我就来给大家分享一下我学习的放大镜特效 下图是原图的样子                                 ...

  8. vue-cli proxyTable中跨域中pathRewrite 解释

      问:proxyTable 里面的pathRewrite里面的‘^/iclient’:'' 什么意思? 答:用代理, 首先你得有一个标识, 告诉他你这个连接要用代理. 不然的话, 可能你的 html ...

  9. VB中preserve的用法

    注:本文转载自:http://zhidao.baidu.com/question/161401549.html ReDim 语句用来定义或重定义原来已经用带空圆括号(没有维数下标)的 Private. ...

  10. 对table最后一行显示与隐藏

    //显示table最后一行,如果用block的话,可能会影响到页面的样式 $("#table tr").get($("#table tr").length - ...