gpt4 book ai didi

java - 为什么Java 8 'Collector' 类是这样设计的?

转载 作者:IT老高 更新时间:2023-10-28 20:55:50 26 4
gpt4 key购买 nike

我们知道 Java 8 引入了一个新的 Stream API,java.util.stream.Collector 是定义如何聚合/收集数据流的接口(interface)。

但是,收集器界面是这样设计的:

public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
BinaryOperator<A> combiner();
Function<A, R> finisher();
}

为什么不是这样设计的?

public interface Collector<T, A, R> {
A supply();
void accumulate(A accumulator, T value);
A combine(A left, A right);
R finish(A accumulator);
}

后一个更容易实现。把它设计成前者是出于什么考虑?

最佳答案

实际上,它最初的设计与您的建议相似。见 the early implementation在项目 lambda 存储库中(makeResult 现在是 supplier)。后来updated到现在的设计。我相信,这种更新的基本原理是简化收集器组合器。我没有找到关于这个主题的任何具体讨论,但我的猜测得到了 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());
}

这个实现只需要重新定义accumulator函数,保持suppliercombinerfinisher不变,所以调用 suppliercombinerfinisher 时没有额外的间接性:您只需直接调用原始收集器返回的函数。 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);
}

这里只改变了finisher,但是使用了原来的supplieraccumulatorcombiner。由于 accumulator 为每个元素调用,因此减少间接性可能非常重要。尝试用你提议的设计重写 mappingcollectingAndThen,你会发现问题。 filteringflatMapping 等新的 JDK-9 收集器也受益于当前的设计。

关于java - 为什么Java 8 'Collector' 类是这样设计的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36928875/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com