Imagine you have a list of people, Roberts, Pauls, Richards, etc, these are people grouped by name into Map<String, List<Person>>. You want to find the oldest Paul, Robert, etc... You can do it like so:
public static void main(String... args) {
        List<Person> people = Arrays.asList(
                new Person(23, "Paul"),
                new Person(24, "Robert"),
                new Person(32, "Paul"),
                new Person(10, "Robert"),
                new Person(4, "Richard"),
                new Person(60, "Richard"),
                new Person(9, "Robert"),
                new Person(26, "Robert")
        );
        Person dummy = new Person(0, "");
        var mapping = people.stream().collect(groupingBy(Person::getName, reducing(dummy, (p1, p2) -> p1.getAge() < p2.getAge() ? p2 : p1)));
        mapping.entrySet().forEach(System.out::println);
    }
Say, I want to get a mapping in the form of Map<String, Integer> instead of Map<String, Person>, I can do it like so:
var mapping = people.stream().collect(groupingBy(Person::getName, mapping(Person::getAge, reducing(0, (p1, p2) -> p1 < p2 ? p2 : p1))));
The steps above are:
Map<String/*Name*/, List<Person>> List<Person> into List<Integer>
I was wondering how to do:
Map<String, List<Person>> Map<String, Person> Map<String, Person> into Map<String, Integer>. And I want to do all that inside that chain of groupingBy's, reducing's and mapping's.This is the "pseudocode":
var mapping = people.stream().collect(groupingBy(Person::getName, reducing(dummy, (p1, p2) -> p1.getAge() < p2.getAge() ? p2 : p1 /*, have to write some other collector factory method here*/)));
How can I achieve this?
It is more straightforward to do this with the 3-argument version of toMap collector:
people.stream().collect(toMap(
        Person::getName, 
        Person::getAge, 
        Integer::max
    ));
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With