Операция должна выполняться после группирования в целом, так как вам необходимо полностью собрать группу, прежде чем вы сможете определить, соответствует ли она критериям.
Вместо сбора карты в другую, похожую карту, Вы можете использовать removeIf
, чтобы удалить несоответствующие группы из карты результатов и добавить эту операцию завершения в сборщик:
Map<KeyType, List<ElementType>> result =
input.stream()
.collect(collectingAndThen(groupingBy(x -> x.id(), HashMap::new, toList()),
m -> {
m.values().removeIf(l -> l.size() <= 5);
return m;
}));
Поскольку сборщик groupingBy(Function)
не дает никаких гарантий относительно изменчивости созданной карты нам нужно указать поставщика для изменяемой карты, которая требует от нас явного указания о нижестоящем коллекторе, поскольку нет перегрузки groupingBy
для указания только функции и поставщика карты.
Если это повторяющийся Задача, мы можем сделать собственный коллектор, улучшающий код, используя его:
public static <T,K,V> Collector<T,?,Map<K,V>> having(
Collector<T,?,? extends Map<K,V>> c, BiPredicate<K,V> p) {
return collectingAndThen(c, in -> {
Map<K,V> m = in;
if(!(m instanceof HashMap)) m = new HashMap<>(m);
m.entrySet().removeIf(e -> !p.test(e.getKey(), e.getValue()));
return m;
});
}
Для большей гибкости этот коллектор позволяет использовать произвольный коллектор, создающий карту, но, поскольку это не обеспечивает тип карты, он будет применять изменяемый карта впоследствии, просто используя конструктор копирования. На практике этого не произойдет, поскольку по умолчанию используется HashMap
. Это также работает, когда вызывающая сторона явно запрашивает LinkedHashMap
для поддержания порядка. Мы могли бы даже поддержать больше случаев, изменив строку на
if(!(m instanceof HashMap || m instanceof TreeMap
|| m instanceof EnumMap || m instanceof ConcurrentMap)) {
m = new HashMap<>(m);
}
К сожалению, не существует стандартного способа определить, является ли карта изменчивой.
Теперь пользовательский коллектор можно использовать как
Map<KeyType, List<ElementType>> result =
input.stream()
.collect(having(groupingBy(x -> x.id()), (key,list) -> list.size() > 5));