2015-10-07 3 views
3

Я хочу сгруппировать коллекцию, но я не хочу, чтобы агрегации включали некоторые значения. Какое лучшее решение для этого?Java8, есть ли сборщик фильтров?

Решение может быть сборщиком filtering(Predicate,Collector), но такого коллекционера нет. Есть ли способ сделать это, не используя свой собственный коллекционер?

IntStream.range(0,100).collect(
    groupingBy(
     i -> i % 3, 
     HashMap::new, 
     filtering(i -> i % 2 == 0, toSet()) 
    ) 
); 

ответ

8

Единственный способ я знаю, чтобы сделать фильтрацию заранее, то есть,

stream.filter(filterPredicate).collect(collector) 

Тем не менее, это не ясно, что вы на самом деле пытаетесь сделать с фильтрацией функция, которая принимает три аргумента вместо двух.

Я подозреваю, что вы пытаетесь отобразить функцию над элементами, которые соответствуют фильтр, но это само по себе карта, которую вы можете сделать достаточно легко:

Collectors.mapping(input -> condition(input) ? function(input) : input, collector) 

И сделать свой собственный коллектор не на самом деле, что трудно:

static <T, A, R> Collector<T, A, R> filtering(
    Predicate<? super T> filter, Collector<T, A, R> collector) { 
    return Collector.of(
     collector.supplier(), 
     (accumulator, input) -> { 
     if (filter.test(input)) { 
      collector.accumulator().accept(accumulator, input); 
     } 
     }, 
     collector.combiner(), 
     collector.finisher()); 
} 
+0

функция фильтрации должна принимать 2 аргумента, исправлена. Результатом является тип «Map >». Я хочу, чтобы наборы содержали только элементы, удовлетворяющие предикату 'i -> i% 2 == 0'. Я не могу отфильтровать коллекцию перед группировкой, потому что тогда результат не будет содержать некоторые группы (в общем случае). –

+0

Тогда я думаю, что вы в значительной степени опустили свой собственный коллекционер, как я описал. –

1

В Java 9 есть новый filtering коллектор:

Map<Department, Set<Employee>> wellPaidEmployeesByDepartment = employees.stream() 
    .collect(groupingBy(Employee::getDepartment, 
     filtering(e -> e.getSalary() > 2000, toSet()))); 

 Смежные вопросы

  • Нет связанных вопросов^_^