Java 在一个过程中执行多个还原

Java 在一个过程中执行多个还原,java,java-8,java-stream,Java,Java 8,Java Stream,在一个流的单个过程中执行多个缩减的习惯用法是什么?如果需要多个类型的缩减计算,即使这违反了SRP,是否只需要一个大的缩减类?可能您希望避免进行多次传递,因为管道级可能会很昂贵。或者您希望避免收集中间值,以便通过多个收集器运行它们,因为存储所有值的成本可能太高 作为,收集器。SummaringInt将收集int值并对其执行多次缩减,返回名为IntSummaryStatistics的聚合结构。有类似的收集器用于汇总双值和长值值 不幸的是,这些只执行一组固定的缩减,因此如果您想执行与它们不同的缩减,您

在一个流的单个过程中执行多个缩减的习惯用法是什么?如果需要多个类型的缩减计算,即使这违反了SRP,是否只需要一个大的缩减类?

可能您希望避免进行多次传递,因为管道级可能会很昂贵。或者您希望避免收集中间值,以便通过多个收集器运行它们,因为存储所有值的成本可能太高

作为,
收集器。SummaringInt
将收集
int
值并对其执行多次缩减,返回名为
IntSummaryStatistics
的聚合结构。有类似的收集器用于汇总
双值
长值

不幸的是,这些只执行一组固定的缩减,因此如果您想执行与它们不同的缩减,您必须编写自己的收集器

这里有一种在一个过程中使用多个无关收集器的技术。我们可以使用
peek()。
peek()
操作需要
使用者
,因此我们需要一种方法将
收集器
调整为
使用者
消费者
将是收集器的累加器功能。但是我们还需要调用收集器的supplier函数,并存储它创建的对象以传递给acculator函数。我们需要一种从收集器中获取结果的方法。为此,我们将收集器包装在一个小助手类中:

public class PeekingCollector<T,A,R> {
    final Collector<T,A,R> collector;
    final A acc;

    public PeekingCollector(Collector<T,A,R> collector) {
        this.collector = collector;
        this.acc = collector.supplier().get();
    }

    public Consumer<T> peek() {
        if (collector.characteristics().contains(Collector.Characteristics.CONCURRENT))
            return t -> collector.accumulator().accept(acc, t);
        else
            return t -> {
                synchronized (this) {
                    collector.accumulator().accept(acc, t);
                }
            };
    }

    public synchronized R get() {
        return collector.finisher().apply(acc);
    }
}
输出为:

[aardvark, alligator, antelope, buffalo, bustard, capybara, cockatoo, crocodile]
{a=[aardvark, antelope, alligator], b=[buffalo, bustard], c=[crocodile, cockatoo, capybara]}
这有点麻烦,因为您必须写出包装收集器的泛型类型(这有点不寻常;它们通常都是推断出来的)。但是,如果处理或存储流值的开销足够大,那么麻烦就值得了


最后请注意,如果流并行运行,则可以从多个线程调用
peek()。因此,非线程安全收集器必须由
synchronized
块保护。如果收集器是线程安全的,我们就不需要同步调用它。为了确定这一点,我们检查收集器的
并发
特性。如果运行并行流,最好在
peek
操作中放置一个并发收集器(例如
groupingByConcurrent
toConcurrentMap
),否则,包装收集器内的同步可能会造成瓶颈并降低整个流的速度。

您是否有要执行的缩减的具体示例?请参阅
收集器。SummaringIT
收集器以获取示例。
[aardvark, alligator, antelope, buffalo, bustard, capybara, cockatoo, crocodile]
{a=[aardvark, antelope, alligator], b=[buffalo, bustard], c=[crocodile, cockatoo, capybara]}