一、接口定义
public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
BinaryOperator<A> combiner();
Function<A, R> finisher();
Set<Characteristics> characteristics();
......省略
}
二、接口泛型<T, A, R>
T : 要处理的元素的类型
A : 累加器的类型
R : 返回结果的类型
三、接口方法
以 Collectors.toList() 为例
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);
}
(1)supplier方法:ArrayList::new,提供了一个ArrayList的累加器A;
A a1 = supplier.get();
(2)accumulator():List::add,将传去的元素T添加到累加器A中,
它接受两个参数,第一个是累加器list,第二个是遍历到的流中的第n个元素;
accumulator.accept(a1, t1);
(3)combiner():(left, right) -> { left.addAll(right); return left; } ,用于并行流执行时合并两个累加器list到一个累加器list中;
A a3 = combiner.apply(a1, a2)
(4)finisher():用于完成时,将累加器的结果A转换成想要的结果R,不需要转换时可以使用 t -> t;表达式表示;
R r1 = finisher.apply(a3);
(5)characteristics(),它会返回一个不可变的Characteristics集合,用于定义
了收集器的行为;
Set<Collector.Characteristics> characteristics = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
(6)创建累加器和结果类型一样的Collector
public static<T, R> Collector<T, R, R> of(Supplier<R> supplier,
BiConsumer<R, T> accumulator,
BinaryOperator<R> combiner,
Characteristics... characteristics) {
(7)创建包含全部收集过程的Collector
public static<T, A, R> Collector<T, A, R> of(Supplier<A> supplier,
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Function<A, R> finisher,
Characteristics... characteristics) {
(8) 枚举 Characteristics
Characteristics包含三种类型:
1、UNORDERED:归约结果不受流中项目的遍历和累积顺序的影响,即流归约结果是无序的,可以并行执行归约。
2、CONCURRENT:accumulator函数可以从多个线程同时调用,且该收集器可以并行归约流。如果收集器没有标为UNORDERED,那它仅在用于无序数据源时才可以并行归约。
3、IDENTITY_FINISH:这表明完成器方法返回的函数是一个恒等函数,可以跳过。这种情况下,累加器对象将会直接用作归约过程的最终结果。这也意味着,将累加器A不加检查地转换为结果R是安全的,即不需要定义finisher,或定义为 t -> t 。
四、接口实现类
CollectorImpl实现了Collector接口,里面仅仅定义了5个函数的实例,接收实例的构造方法以及各个函数的get方法。
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;
}
}
总结
要想更好的理解流式编程,学习Collertor接口是必不可少的,不仅要学习jdk中已经实现了的Collertor,更要学会定义适合自己业务的Collertor。