Java流分类并按计数过滤(HAVING)

问题描述 投票:1回答:2

Java(9+)流是否支持类似于SQL的HAVING子句?用例:分组,然后删除具有特定计数的所有组。是否可以将以下SQL子句编写为Java流?

GROUP BY id
HAVING COUNT(*) > 5

我能想到的最接近的是:

input.stream()
        .collect(groupingBy(x -> x.id()))
        .entrySet()
        .stream()
        .filter(entry -> entry.getValue().size() > 5)
        .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

但是提取分组结果的entrySet以收集两次感到很奇怪,尤其是终端collect调用基本上是将映射映射到其自身。

[我看到有collectingAndThenfiltering个收集器,但是我不知道它们是否可以解决我的问题(或者更确切地说,如何正确应用它们)。

是否有上述的更好(更惯用的)版本,还是我坚持收集到中间图,将其过滤然后收集到最终图上?

java group-by java-stream having
2个回答
2
投票

如果您想获得更具可读性的代码,也可以使用Guava filterValues function(作为重排代码)

[它允许转换地图,有时比Java流提供更短,更易读的语法。

Map<A,B> unfiltered = java stream groupingby
return Maps.filterValues(unfiltered, value -> value.size() > 5);

0
投票

是,您重新播放Map

相当于SELECT id, COUNT(*) FROM input GROUP BY id HAVING COUNT(*) > 5是:

Map<Integer, Long> result = input.stream()
        .collect(Collectors.groupingBy(i -> i.getId(), Collectors.counting()))
        .entrySet().stream()
        .filter(e -> e.getValue() > 5)
        .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

替代:

Map<Integer, Long> result = input.stream()
        .collect(Collectors.groupingBy(i -> i.getId(), Collectors.counting()));
result.values().removeIf(cnt -> cnt <= 5);
© www.soinside.com 2019 - 2024. All rights reserved.