Java 8 группировка с использованием пользовательского коллектора?

У меня есть следующий class.

class Person { String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { return birthday.until(IsoChronology.INSTANCE.dateNow()).getYears(); } public String getName() { return name; } } 

Я хотел бы иметь возможность группировать по возрасту, а затем собирать список имен лиц, а не самого объекта Person; все в одном хорошем выражении ламбы.

Чтобы упростить все это, я связываю свое текущее решение, которое хранит результат группировки по возрасту, а затем выполняет итерацию по ней для сбора имен.

 ArrayList members = new ArrayList(); members.add(new OtherPerson("Fred", IsoChronology.INSTANCE.date(1980, 6, 20), OtherPerson.Sex.MALE, "[email protected]")); members.add(new OtherPerson("Jane", IsoChronology.INSTANCE.date(1990, 7, 15), OtherPerson.Sex.FEMALE, "[email protected]")); members.add(new OtherPerson("Mark", IsoChronology.INSTANCE.date(1990, 7, 15), OtherPerson.Sex.MALE, "[email protected]")); members.add(new OtherPerson("George", IsoChronology.INSTANCE.date(1991, 8, 13), OtherPerson.Sex.MALE, "[email protected]")); members.add(new OtherPerson("Bob", IsoChronology.INSTANCE.date(2000, 9, 12), OtherPerson.Sex.MALE, "[email protected]")); Map<Integer, List> collect = members.stream().collect(groupingBy(Person::getAge)); Map<Integer, List> result = new HashMap(); collect.keySet().forEach(key -> { result.put(key, collect.get(key).stream().map(Person::getName).collect(toList())); }); 

Текущее решение

Не идеально и ради обучения я хотел бы иметь более элегантное и эффективное решение.

    При группировке Stream с Collectors.groupingBy вы можете указать операцию сокращения значений с помощью пользовательского Collector . Здесь нам нужно использовать Collectors.mapping , которое принимает функцию (что такое отображение) и сборщик (как собирать отображаемые значения). В этом случае отображением является Person::getName , то есть ссылка на метод, которая возвращает имя Person, и мы собираем это в List .

     Map> collect = members.stream() .collect(Collectors.groupingBy( Person::getAge, Collectors.mapping(Person::getName, Collectors.toList())) ); 

    Вы также можете использовать Collectors.toMap и предоставить сопоставление для функции key, value и merge (если есть).

     Map ageNameMap = members.stream() .collect(Collectors.toMap( person -> person.getAge(), person -> person.getName(), (pName1, pName2) -> pName1+"|"+pName2) ); 

    Вы можете использовать mapping Collector для сопоставления списка Person с именами людей:

     Map> collect = members.stream() .collect(Collectors.groupingBy(Person::getAge, Collectors.mapping(Person::getName, Collectors.toList()))); 
    Interesting Posts

    Использование JAXB для перекрестных ссылок XmlID из двух XML-файлов

    Управление количеством десятичных цифр в печатном выходе в R

    Когда функция слишком длинная?

    Повторяющиеся линии фрагментов MP3

    Как я могу обрабатывать исключения времени ожидания проверки подлинности в ASP.NET?

    Почему я не могу использовать значение float в качестве параметра шаблона?

    Как определить, реализует ли тип определенного типа общего типа

    Почему Java Calendar установлен (int year, int month, int date), не возвращает правильную дату?

    Как составить `не` с функцией произвольной arity?

    Угловые динамические вкладки с выбранными компонентами

    Проблемы с новой строкой в ​​Graphics2D.drawString

    Индекс максимального и минимального значения в массиве

    Смешивание отладки и выпуска библиотеки / двоичного кода – неправильная практика?

    Создание параметров URL-запроса из объектов NSDictionary в ObjectiveC

    Элементы панели инструментов Visual Studio 2010 отключены или неактивны

    Давайте будем гением компьютера.