public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
BinaryOperator<A> combiner();
Function<A, R> finisher();
Set<Characteristics> characteristics();
public static<T, R> Collector<T, R, R> of(Supplier<R> supplier,
BiConsumer<R, T> accumulator,
BinaryOperator<R> combiner,
Characteristics... characteristics) {
Objects.requireNonNull(supplier);
Objects.requireNonNull(accumulator);
Objects.requireNonNull(combiner);
Objects.requireNonNull(characteristics);
Set<Characteristics> cs = (characteristics.length == 0)
? Collectors.CH_ID
: Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH,
characteristics));
return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, cs);
}
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) {
Objects.requireNonNull(supplier);
Objects.requireNonNull(accumulator);
Objects.requireNonNull(combiner);
Objects.requireNonNull(finisher);
Objects.requireNonNull(characteristics);
Set<Characteristics> cs = Collectors.CH_NOID;
if (characteristics.length > 0) {
cs = EnumSet.noneOf(Characteristics.class);
Collections.addAll(cs, characteristics);
cs = Collections.unmodifiableSet(cs);
}
return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, finisher, cs);
}
enum Characteristics {
CONCURRENT,
UNORDERED,
IDENTITY_FINISH
}
}
上面的代码是java8中Collector接口源码删除注解以后的样子。
Collector<T, A, R> :T 是流中要收集的项目的泛型;
A 是累加器的类型,累加器是在收集过程中用于累积部分结果的对象;
R 是收集器操作得到的对象的类型。
Supplier<A> supplier(); //Collector声明的第一个方法
supplier方法必须返回一个结果为空的Supplier,也就是一个无参数函数,在调用它时会创建一个空的累加器实例,供数据收集过程使用。
补充知识点:
package java.util.function;
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Supplier<T>这个泛型接口是一个函数式接口,因为它只有一个抽象方法。这是一个供应商,提供者.就如一个工厂一样。
该接口只提供一个空空的壳子,到底返回什么实际是自己传进去的,也就是你自己传进去的T,然后可以调用Get();方法返回一个T;
第二个方法:BiConsumer<A, T> accumulator(); 功能:将元素添加到结果容器
该方法将会返回执行规约操作的函数。A 表示累加器,保存规约操作的结果, T表示参加规约的下一个元素。
第三个方法:Function<A, R> finisher(); // 结果转换
对结果容器应用最终转换, 累加器对象转换为整个集合操作的最终结果。
有以上三个方法就可以应对规约操作了。但是为了应对更复杂的情况:延迟效应和并行规约。于是还必须有下面这个方法。
第四个方法:BinaryOperator<A> combiner(); 将两个结果容器合并
第五个方法:Set<Characteristics> characteristics(); //返回一个不可变的Characteristics集合。
返回枚举里的三个项目:
/** * Indicates that this collector is <em>concurrent</em>, meaning that * the result container can support the accumulator function being * called concurrently with the same result container from multiple * threads. * * <p>If a {@code CONCURRENT} collector is not also {@code UNORDERED}, * then it should only be evaluated concurrently if applied to an * unordered data source. */
CONCURRENT, /** * Indicates that the collection operation does not commit to preserving * the encounter order of input elements. (This might be true if the * result container has no intrinsic order, such as a {@link Set}.) */ UNORDERED, /** * Indicates that the finisher function is the identity function and * can be elided. If set, it must be the case that an unchecked cast * from A to R will succeed. */ IDENTITY_FINISH
CONCURRENT:表示规约结果不受流中项目的遍历和积累顺序的影响;
UNORDERED: accumulator函数可以从多个线程同时调用,且该收集器可以并行规约流;
IDENTITY_FINISH: 这表明完成器返回的方法函数是一个恒等函数,可以跳过。
下面看看ToListCollector收集器是如何实现上面五个函数的:
##?