pop*_*rny 34 java java-8 java-stream collectors
我们知道Java 8引入了一个新的Stream API,并且java.util.stream.Collector是定义如何聚合/收集数据流的接口.
但是,Collector接口的设计如下:
public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
BinaryOperator<A> combiner();
Function<A, R> finisher();
}
Run Code Online (Sandbox Code Playgroud)
为什么它的设计不符合以下规定?
public interface Collector<T, A, R> {
A supply();
void accumulate(A accumulator, T value);
A combine(A left, A right);
R finish(A accumulator);
}
Run Code Online (Sandbox Code Playgroud)
后者更容易实现.将它设计为前者的考虑是什么?
Tag*_*eev 26
实际上它最初设计的类似于你的建议.查看项目lambda存储库中的早期实现(makeResult现在是supplier).后来更新到了当前的设计.我相信,这种更新的基本原理是简化收集器组合器.我没有找到关于这个主题的具体讨论,但我的猜测得到了mapping收集器出现在同一变更集中的事实的支持.考虑实施Collectors.mapping:
public static <T, U, A, R>
Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
Collector<? super U, A, R> downstream) {
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());
}
Run Code Online (Sandbox Code Playgroud)
此实现只需重新定义accumulator函数,离开supplier,combiner并且finisher因此在调用时没有额外的间接supplier,combiner或者finisher:您只需直接调用原始收集器返回的函数.它更重要的是collectingAndThen:
public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
Function<R,RR> finisher) {
// ... some characteristics transformations ...
return new CollectorImpl<>(downstream.supplier(),
downstream.accumulator(),
downstream.combiner(),
downstream.finisher().andThen(finisher),
characteristics);
}
Run Code Online (Sandbox Code Playgroud)
这里只finisher改变了,但是原创的supplier,accumulator并且combiner被使用了.正如accumulator每个元素所要求的那样,减少间接可能非常重要.尝试重写mapping并collectingAndThen使用您提出的设计,您将看到问题.新的JDK-9收藏家喜欢filtering并且flatMapping也受益于当前的设计.
S.D*_*.D. 18
您问题中的第一个模式是模块配置.Collector接口的实现可以为Supplier,Accumulator等提供不同的实现.这意味着可以从现有的Supplier,Accumulator等实现池中组合 Collector实现.这也有助于重用,两个收集器可能使用相同的Accumulator实现.在Stream.collect()使用提供的行为.
在第二种模式中,收集器实现必须自己实现所有功能.各种变体都需要覆盖父实现.如果两个收集器具有类似于步骤的逻辑,例如累积,则重用的范围不大,加上代码重复.
| 归档时间: |
|
| 查看次数: |
2298 次 |
| 最近记录: |