且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用流从列表中获取总和和最大值

更新时间:2023-02-10 22:48:28

如果你想在一次通过中找到每月计数和每月最大计数的日期,我认为你需要一个自定义收集器。

If you want to find both the sum of counts per month and the day with the max count per month in a single pass, I think you need a custom collector.

首先,让我们创建一个持有者类来存储结果:

First, let's create a holder class where to store the results:

public class Statistics {

    private final String dayWithMaxCount;

    private final long totalCount;

    public Statistics(String dayWithMaxCount, long totalCount) {
        this.dayWithMaxCount = dayWithMaxCount;
        this.totalCount = totalCount;
    }

    // TODO getters and toString
}

然后,创建此方法d,返回一个收集器,累加计数和最大计数的总和,以及找到该最大值的那一天:

Then, create this method, which returns a collector that accumulates both the sum of counts and the max count, along with the day in which that max was found:

public static Collector<MonthlyTransaction, ?, Statistics> withStatistics() {
    class Acc {
        long sum = 0;
        long maxCount = Long.MIN_VALUE;
        String dayWithMaxCount;

        void accumulate(MonthlyTransaction transaction) {
            sum += transaction.getCount();
            if (transaction.getCount() > maxCount) {
                maxCount = transaction.getCount();
                dayWithMaxCount = transaction.getDay();
            }
        }

        Acc merge(Acc another) {
            sum += another.sum;
            if (another.maxCount > maxCount) {
                maxCount = another.maxCount;
                dayWithMaxCount = another.dayWithMaxCount;
            }
            return this;
        }

        Statistics finish() {
            return new Statistics(dayWithMaxCount, sum);
        }
    }
    return Collector.of(Acc::new, Acc::accumulate, Acc::merge, Acc::finish);
}

这使用本地类 Acc 累积并合并部分结果。 完成方法返回 Statistics 类的实例,该类保存最终结果。最后,我正在使用 Collector.of 基于 Acc 类的方法创建收集器。

This uses the local class Acc to accumulate and merge partial results. The finish method returns an instance of the Statistics class, which holds the final results. At the end, I'm using Collector.of to create a collector based on the methods of the Acc class.

最后,您可以使用上面定义的方法和类,如下所示:

Finally, you can use the method and class defined above as follows:

Map<String, Statistics> statisticsByMonth = transactions.stream()
    .collect(Collectors.groupingBy(MonthlyTransaction::getMonth, withStatistics()));