【问题标题】:Calculate percentage of a value using stream使用流计算值的百分比
【发布时间】:2020-06-25 19:08:20
【问题描述】:

我试图弄清楚在使用stream 时如何计算列表中特定值的百分比。

我的对象getTag 可以取值GY,我想计算G:s 在列表中的百分比。另一个对象是getDateTime,其形式为1946-01-12

我有条件filter(weather -> !weather.getDateTime().isAfter(dateTo) && !weather.getDateTime().isBefore(dateFrom)),因为我只想要用户输入的两个日期之间的百分比。

所以每个 DateTime 值对应于GY。我用Collectors.counting()计算了GY的频率,但是如何得到百分比呢?

Map<String, Long> percentage = weatherData.stream()
        .filter(weather -> !weather.getDateTime().isAfter(dateTo) && !weather.getDateTime().isBefore(dateFrom))
        .collect(Collectors.groupingBy(Weather::getTag, Collectors.counting()));

【问题讨论】:

    标签: java hashmap java-stream percentage collectors


    【解决方案1】:

    如果您将您关心的项目 ("G") 映射为 1,而将其他所有项目映射为 0,则平均值是流中“G”的百分比。

    double pctG = list.stream()
        .mapToInt(obj -> obj.getTag().equals("G") ? 1 : 0)
        .summaryStatistics()
        .getAverage();
    

    使用Java 13,您可以使用teeing()收集器按标签统计元素,过滤后的元素总数,最后将组数除以总数: p>

    Map<String, Double> fractions = weatherData.stream()
            .filter(...)
            .collect(
                Collectors.teeing(
                    Collectors.groupingBy(Weather::getTag, Collectors.counting()),
                    Collectors.counting(),
                    YourClass::scale));
    

    scale() 函数将每个组除以总数:

    static <T> Map<T, Double> scale(Map<? extends T, Long> counts, long total) {
        return counts.entrySet().stream().
            .collect(Collectors.toMap(e -> e.getKey(), ((double) e.getValue()) / total));
    }
    

    【讨论】:

    • items.size() 作为值被传递下去是什么?这里没有什么叫items
    • @Naman 抱歉打错了。它应该是列表的大小,但现在我发现这并没有考虑过滤......
    • 编辑的问题是缩放因子是一个不正确的值。 (因为filter)。简而言之,除了我所知的 SummaryStatistics 之外,没有直接的方法来处理在终端操作之前对元素进行计数。..
    • @Naman 没错,这就是我的评论的意思。我会更新的。
    • 就(近似)正确性而言,您可能希望将其拆分为两个操作,例如在List&lt;Weather&gt; validDates = weatherData.stream().filter(weather -&gt; !weather.getDateTime().isAfter(dateTo) &amp;&amp; !weather.getDateTime().isBefore(dateFrom)).collect(Collectors.toList()); 中计数,然后在Map&lt;LocalDate, Double&gt; countByDate = validDates.stream().collect(Collectors.groupingBy(Weather::getDateTime, Collectors.collectingAndThen(Collectors.counting(), a -&gt; (double) a / validDates.size()))); 中评估百分比
    猜你喜欢
    • 2013-11-15
    • 2015-10-11
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    相关资源
    最近更新 更多