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
调用基本上是将映射映射到其自身。
[我看到有collectingAndThen
和filtering
个收集器,但是我不知道它们是否可以解决我的问题(或者更确切地说,如何正确应用它们)。
是否有上述的更好(更惯用的)版本,还是我坚持收集到中间图,将其过滤然后收集到最终图上?
如果您想获得更具可读性的代码,也可以使用Guava filterValues function
(作为重排代码)
[它允许转换地图,有时比Java流提供更短,更易读的语法。
Map<A,B> unfiltered = java stream groupingby
return Maps.filterValues(unfiltered, value -> value.size() > 5);
是,您重新播放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);