首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在java streams inside collect中如何将Map<String、Person>转换为Map<String、Integer>?

在java streams inside collect中如何将Map<String、Person>转换为Map<String、Integer>?
EN

Stack Overflow用户
提问于 2018-05-30 07:47:25
回答 3查看 195关注 0票数 4

假设你有一个人的列表,罗伯茨,保罗,理查兹等等,这些人按名字分组到Map<String, List<Person>>中。你想找最年长的保罗,罗伯特,等等。你可以这样做:

代码语言:javascript
复制
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);
    }

比方说,我想以Map<String, Integer>而不是Map<String, Person>的形式获得一个映射,我可以这样做:

代码语言:javascript
复制
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<Integer>
  • Find最大整数。

我想知道该怎么做:

  • 按名称分组到Map<String, List<Person>>
  • 查找每个组名称中年龄最大的人,让Map<String, Person>
  • Map<String, Person>转换为Map<String, Integer>。我想在groupingBy's链中完成所有这些操作,减少‘s和And’s。

这是“伪代码”:

代码语言:javascript
复制
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*/)));

我如何才能做到这一点?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-05-30 10:47:27

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

代码语言:javascript
复制
final Map<String, Integer> oldestPersonByName = people.stream()
        .collect(Collectors.groupingBy(Person::getName, Collectors.reducing(0, Person::getAge, Integer::max)));

对于reduce,您必须传递一个标识元素、映射函数和一个用于reduce的二元运算符,在本例中为max

票数 3
EN

Stack Overflow用户

发布于 2018-05-30 08:29:06

使用3-argument version of toMap collector可以更直接地完成此操作

代码语言:javascript
复制
people.stream().collect(toMap(
        Person::getName, 
        Person::getAge, 
        Integer::max
    ));
票数 4
EN

Stack Overflow用户

发布于 2018-05-30 08:06:54

我认为它会像下面这样,同样使用maxBy而不是reducing

代码语言:javascript
复制
people.stream().collect(
    groupingBy(
        Person::getName,
        collectingAndThen(
            maxBy(Comparator.comparing(Person::getAge)),
            (Optional<Person> max) -> max.get().getAge()
        )
    )
);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50594490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档