Java(9+)ストリームは、SQLと同様のHAVING
句をサポートしていますか?使用例:グループ化してから特定の数のすべてのグループを削除します。次のSQLを書くことは可能ですか? Java stream?
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を2回収集して抽出することは奇妙に感じられ、特にターミナルcollect
の呼び出しは基本的にマップをそれ自体にマッピングしています。
collectingAndThen
およびfiltering
コレクターがあることがわかりますが、それらが私の問題を解決するかどうか(またはそれらを正しく適用する方法)がわかりません。
上記のより良い(より慣用的な)バージョンはありますか、それとも中間マップに収集し、それをフィルタリングしてから最終マップに収集するのに行き詰まっていますか?
私が知っている唯一の方法は Collectors.collectingAndThen
finisher
関数内で同じ実装を使用:
Map<Integer, List<Item>> a = input.stream().collect(Collectors.collectingAndThen(
Collectors.groupingBy(Item::id),
map -> map.entrySet().stream()
.filter(e -> e.getValue().size() > 5)
.collect(Collectors.toMap(Entry::getKey, Entry::getValue))));
より読みやすいコードが必要な場合は、(再ストリームの代替として)Guava filterValues
関数を使用することもできます。
これはマップの変換を可能にし、Javaストリームよりも短くて読みやすい構文を提供することがあります。
Map<A,B> unfiltered = Java stream groupingby
return Maps.filterValues(unfiltered, value -> value.size() > 5);