Как составить список всех объектов с максимальным значением данного атрибута, используя поток? - PullRequest
0 голосов
/ 08 февраля 2019

Скажем, у меня есть список People с атрибутами name и age.Как получить все экземпляры People, которые имеют наибольшее значение для возраста атрибута, используя поток?

В настоящее время я использую двухэтапный подход:

1) Поискмаксимальное значение возраста

int maxAge = group
        .stream()
        .mapToInt(person -> person.getAge())
        .max()
        .orElse(-1);

2) Создание списка People с этим возрастом

List<Group> groupWithMaxAge = group
        .stream()
        .filter(person -> person.getAge() == maxAge)
        .collect(Collectors.toList());

Не беспокойтесь, это работает.Однако рассмотрим случай, когда вычисление возраста является дорогой функцией.В таком случае было бы неплохо, если бы вы могли сделать это за один раз, не так ли?

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Более понятный способ - использовать Stream.max как:

List<Group> groupWithMaxAge = group.stream() // Stream<Group>
    .collect(Collectors.groupingBy(Group::getAge)) // Map<Integer, List<Group>
    .entrySet() // Set<Entry<Integer, List<Group>>>
    .stream().max(Comparator.comparingInt(Entry::getKey)) // Optional<Entry<Integer, List<Group>>>
    .map(Entry::getValue) // Optional<List<Person>>
    .orElse(new ArrayList<>());
0 голосов
/ 08 февраля 2019

Вы также можете использовать groupingBy с TreeMap как mapFactory:

List<Group> list = people.stream()
            .collect(groupingBy(Group::getAge, TreeMap::new, toList()))
            .lastEntry()
            .getValue();
0 голосов
/ 08 февраля 2019

Альтернативой является группировка и выбор максимальной клавиши (age):

List<People> peopleWithMaxAge = group.stream()
        .collect(Collectors.groupingBy(People::getAge))
        .entrySet()
        .stream()
        .sorted(Comparator.<Entry<Integer, List<People>>>comparingInt(Entry::getKey)
                .reversed())
        .findFirst()
        .map(Entry::getValue)
        .orElse(new ArrayList<>()); //empty list if original was empty
...