如何将Map <string,person =“”>转换为map <string,integer =“”>在java流中收集?

时间:2018-05-29 23:47:25

标签: java java-8 java-stream

想象一下,你有一个人名单,Roberts,Pauls,Richards等,这些是按姓名分组到Map<String, List<Person>>的人。你想找到最老的保罗,罗伯特等......你可以这样做:

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);
    }

说,我希望以[{1}}而不是Map<String, Integer>的形式获得映射,我可以这样做:

Map<String, Person>

上述步骤为:

  • 按名称分组到var mapping = people.stream().collect(groupingBy(Person::getName, mapping(Person::getAge, reducing(0, (p1, p2) -> p1 < p2 ? p2 : p1))));
  • Map<String/*Name*/, List<Person>>映射到List<Person>
  • 在这些列表中查找最大整数。

我想知道该怎么做:

  • 按名称分组到List<Integer>
  • 找到每个群组名称中最老的人,获取Map<String, List<Person>>
  • Map<String, Person>转换为Map<String, Person>。我想在分组链中做所有这些,减少和映射。

这是&#34;伪代码&#34;:

Map<String, Integer>

我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:4)

使用3-argument version of toMap collector

执行此操作更为直接
people.stream().collect(toMap(
        Person::getName, 
        Person::getAge, 
        Integer::max
    ));

答案 1 :(得分:3)

如果你真的想使用问题陈述中提到的groupingBy,你仍然可以这样做:

final Map<String, Integer> oldestPersonByName = people.stream()
        .collect(Collectors.groupingBy(Person::getName, Collectors.reducing(0, Person::getAge, Integer::max)));

对于减少,你必须传递一个标识元素,映射函数和用于减少的二元运算符,在这种情况下为max

答案 2 :(得分:2)

我认为它会像以下一样,也使用maxBy代替reducing

people.stream().collect(
    groupingBy(
        Person::getName,
        collectingAndThen(
            maxBy(Comparator.comparing(Person::getAge)),
            (Optional<Person> max) -> max.get().getAge()
        )
    )
);