Java 同时汇总和收集流元素

Java 同时汇总和收集流元素,java,stream,Java,Stream,使用java streams api,我希望获得SummaryStatistics min、max等,并同时将所有对象收集到ArrayList中 下面给出了一个异常,因为该流已经使用summaryStatistics调用进行了处理 这两个操作可以合并为一个操作吗 代码示例: IntSummaryStatistics summaryStatistics = statistics.mapToInt(Statistic::getSpread) .summaryStatistics();

使用java streams api,我希望获得SummaryStatistics min、max等,并同时将所有对象收集到ArrayList中

下面给出了一个异常,因为该流已经使用summaryStatistics调用进行了处理

这两个操作可以合并为一个操作吗

代码示例:

IntSummaryStatistics summaryStatistics = statistics.mapToInt(Statistic::getSpread)
        .summaryStatistics();

List<Statistics> statsList = statistics.collect(Collectors.toList());

谢谢。

例如,如果您将元素作为mapToInt功能的副作用添加到列表中,则有可能:

List<Statistics> statsList = new ArrayList<>();
IntSummaryStatistics summaryStatistics = 
    statistics.mapToInt(s -> {statsList.add(s); return s.getSpread();})
              .summaryStatistics();

例如,如果将元素作为mapToInt函数的副作用添加到列表中,则有可能:

List<Statistics> statsList = new ArrayList<>();
IntSummaryStatistics summaryStatistics = 
    statistics.mapToInt(s -> {statsList.add(s); return s.getSpread();})
              .summaryStatistics();

从Java 12开始,根据文档,有:

返回由两个下游收集器组成的收集器。传递给结果收集器的每个元素都由两个下游收集器处理,然后使用指定的合并函数将它们的结果合并到最终结果中

因此,在您的情况下,您可以在今天使用它:

Result result = statistics.collect(
    Collectors.teeing(
        Collectors.summarizingInt(Statistic::getSpread),
        Collectors.toList(),
        Result::new));
其中结果如下:

public class Result {

    private final IntSummaryStatistics stats;

    private final List<Statistic> list;

    Result(IntSummaryStatistics stats, List<Statistic> list) {
        this.stats = stats;
        this.list = list;
    }

    // getters
}

从Java 12开始,根据文档,有:

返回由两个下游收集器组成的收集器。传递给结果收集器的每个元素都由两个下游收集器处理,然后使用指定的合并函数将它们的结果合并到最终结果中

因此,在您的情况下,您可以在今天使用它:

Result result = statistics.collect(
    Collectors.teeing(
        Collectors.summarizingInt(Statistic::getSpread),
        Collectors.toList(),
        Result::new));
其中结果如下:

public class Result {

    private final IntSummaryStatistics stats;

    private final List<Statistic> list;

    Result(IntSummaryStatistics stats, List<Statistic> list) {
        this.stats = stats;
        this.list = list;
    }

    // getters
}

最简单的解决方案是收集到一个列表,然后对该列表执行后续操作

List<Statistics> statsList = statistics.collect(Collectors.toList());

IntSummaryStatistics summaryStatistics = statsList.stream()
        .mapToInt(Statistic::getSpread)
        .summaryStatistics();

最简单的解决方案是收集到一个列表,然后对该列表执行后续操作

List<Statistics> statsList = statistics.collect(Collectors.toList());

IntSummaryStatistics summaryStatistics = statsList.stream()
        .mapToInt(Statistic::getSpread)
        .summaryStatistics();

是的,很简单。困扰我的是创建列表,这意味着要遍历整个流程。然后,为了获得统计数据,您必须再次遍历流。为什么这会困扰您?我必须处理非常大的数据集。如果要将它们收集到内存列表中,数据集就不会那么大。同样,迭代流一次,每个项做两件工作并不一定比迭代流两次更有效。是的,这很简单。困扰我的是创建列表,这意味着要遍历整个流程。然后,为了获得统计数据,您必须再次遍历流。为什么这会困扰您呢?我必须处理非常大的数据集。如果要将它们收集到内存列表中,数据集就不会那么大。同样,迭代流一次,每个项做两件工作并不一定比迭代流两次更有效。@MikeFHay谢谢你的编辑!我应该说明我使用的是java 11,但是谢谢你提供的信息。。。这就是我所希望的。@Albert2Rocks我将使用Collectors.teeing方法添加一个编辑code@MikeFHay谢谢你的编辑!我应该说明我使用的是java 11,但是谢谢你提供的信息。。。这就是我所希望的。@Albert2Rocks我将添加一个对收集器的编辑。teeing方法的代码您的统计数据流的来源是什么?只是想知道,为什么要将其收集到结果中的列表中?统计数据流的来源是什么?只是想知道,为什么要将其收集到结果中的列表中?