Как отфильтровать возраст при группировке по карте со списком - PullRequest
0 голосов
/ 20 декабря 2018

Как и в моем предыдущем вопросе здесь , Пользователь объекты, которые у меня есть, это

new User("ayush","admin",23)
new User("ashish","guest",19) 
new User("ashish","admin",20) 
new User("garima","guest",29)
new User("garima","super",45)
new User("garima","guest",19)

Теперь я пытаюсь получить название для разных возрастных трендовдля этих пользователей.Но мне нужно отфильтровать их выше threshold возраста.Я мог бы получить тренд, используя

Map<String, List<Integer>> userNameAndAgeTrend = users.stream().collect(Collectors.groupingBy(user-> user.getName(), Collectors.mapping(u-> u.getAge(), toList())));

, это дает мне {ashish=[19, 20], garima=[29, 45, 19], ayush=[23]}.Но я не могу правильно отфильтровать список, используя пороговое значение, например 21 год , в моей ситуации с использованием такой группировки.Может кто-нибудь помочь, пожалуйста?

Кроме того, использование .filter(user -> user.getAge() > 21) не дает сопоставления для ashish, что я тоже хочу сохранить.Я могу использовать Java10, установленный на моей машине, и пробовать предложенные решения.

Ответы [ 3 ]

0 голосов
/ 20 декабря 2018

Вам необходимо добавить операцию .filter() перед .collect() one

Map<String, List<Integer>> userNameAndAgeTrend = 
                      users.stream()
                           .filter(user -> user.getAge() > 21)
                           .collect(Collectors.groupingBy(user-> user.getName(), Collectors.mapping(u-> u.getAge(), toList())));
0 голосов
/ 20 декабря 2018

, если вы хотите filter до группировки:

users.stream()
     .filter(u -> u.getAge() > 21) //<--- apply the filter operation
     ...

filter - это промежуточная операция, которая позволяет "сохранить элементы, которые удовлетворяют предоставленному предикату", иисключите другие, которые этого не делают.

Итак, после операции filter у вас есть новый поток, состоящий только из элементов, которые передают предоставленный предикат.в этом случае только пользователи, чей возраст старше 21 *. 1011 *


, если вы хотите filter после группировки (не путать с filter в потоке,это немного отличается)

сборщик filtering по состоянию на JDK9:

users.stream()
     .collect(groupingBy(User::getName, 
            filtering(u -> u.getAge() > 21, 
                   mapping(User::getAge, toList()))));

см. принятый ответ здесь для реализации JDK8.

С потоком filter выше значения сначала фильтруются, а затем группируются.другими словами, после фильтрации у нас их нет «следов».

Однако, с коллектором filtering с JDK9 мы можем поддерживать след.

0 голосов
/ 20 декабря 2018

Stream.filter

Вы можете использовать filter как

Map<String, List<Integer>> userNameAndAgeTrend = users.stream()
        .filter(a -> a.getAge() > 21) // only above 21
        .collect(Collectors.groupingBy(User::getName, Collectors.mapping(User::getAge, Collectors.toList())));

Как подтверждается вами в комментариях, это даст вам в качестве вывода

{garima=[29, 45], ayush=[23]}

Collectors.filtering

Если вы ищете все имена, вы также можете использовать Collectors.filtering, начиная с , который явно вызывает похожее поведение (форматирование мое):

Использование коллектора filtering, как показано выше приведет котображение из этого отдела в пустой набор .

Если вместо этого была выполнена операция потока filter(), не было бы сопоставления для этого отдела вообще .

Егоиспользование должно выглядеть примерно так:

Map<String, List<Integer>> userNameAndAgeTrend = users.stream()
        .collect(Collectors.groupingBy(User::getName, Collectors.mapping(User::getAge, 
                        Collectors.filtering(age -> age > 21, Collectors.toList()))));

, и результат теперь будет

{ashish=[], garima=[29, 45], ayush=[23]}
...