【问题标题】:Count Java Stream to Integer, not Long将 Java 流计数为整数,而不是长
【发布时间】:2020-12-03 10:41:10
【问题描述】:

我需要统计一些特殊捆绑包的出现次数。

Map<Integer,Integer> countBundles(){
    return bundles.stream()
        .bla()
        .bla()
        .bla()
        .collect(groupingBy(Bundle::getId), counting()));
}

此代码无法编译,因为计数返回 Long。 有什么漂亮的方法可以返回 Map

我有这个想法,但是很丑

  map.entrySet().stream()
     .collect(toMap(Map.Entry::getKey, entry -> (int) entry.getValue().longValue()));

【问题讨论】:

  • 应该没有其他方法可以使用Streams API。除此之外,我不同意您到目前为止所尝试的内容是丑陋的,因为这看起来像是遵循功能类型的明显方法。
  • 此链接对您有帮助吗? stackoverflow.com/questions/51968025/…

标签: java java-stream collectors


【解决方案1】:

没有将Collectors.counting()Integer 结合使用的内置方法,因为泛型是不变的。但是,您可以轻松编写自定义Collector

public static <T> Collector<T, ?, Integer> countingInt() {
    return Collectors.summingInt(e -> 1);
}

如果您只想使用原生库,也可以使用普通的summingInt(e -&gt; 1)

例子:

Map<Integer,Integer> countBundles(){
    return bundles.stream()
        .bla()
        .bla()
        .bla()
   // 1 .collect(groupingBy(Bundle::getId), countingInt()));
   // 2 .collect(groupingBy(Bundle::getId), summingInt(e -> 1)));
}

请注意,使用签名解释,您最多可以计算 2.147.483.647 个元素。

【讨论】:

    【解决方案2】:

    您可以使用Collectors.collectingAndThen 将函数应用于收集器的结果:

    Map<Integer,Integer> countBundles() {
        return bundles.stream()
            .bla()
            .bla()
            .bla()
            .collect(groupingBy(Bundle::getId, collectingAndThen(counting(), Long::intValue)));
    }
    

    如果您需要其他语义而不只是强制转换,请将 Long::intValue 替换为其他转换代码。

    【讨论】:

    • 为了检测 int 溢出,我推荐使用Math::toIntExact
    猜你喜欢
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 2019-10-17
    • 2014-11-30
    • 2011-05-30
    • 2011-10-05
    • 1970-01-01
    • 2020-08-24
    相关资源
    最近更新 更多