使用自定义收集器进行Java 8分组? [英] Java 8 grouping using custom collector?

查看:99
本文介绍了使用自定义收集器进行Java 8分组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程。

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对象本身;所有这些都在一个漂亮的lamba表达式中。

I'd like to be able to group by age and then collect the list of the persons names rather than the Person object itself; all in a single nice lamba expression.

为了简化所有这一切,我将链接我当前的解决方案,该解决方案按年龄存储分组结果,然后迭代它以收集名称。

To simplify all of this I am linking my current solution that store the result of the grouping by age and then iterates over it to collect the names.

ArrayList<OtherPerson> members = new ArrayList<>();

members.add(new OtherPerson("Fred", IsoChronology.INSTANCE.date(1980, 6, 20), OtherPerson.Sex.MALE, "fred@example.com"));
members.add(new OtherPerson("Jane", IsoChronology.INSTANCE.date(1990, 7, 15), OtherPerson.Sex.FEMALE, "jane@example.com"));
members.add(new OtherPerson("Mark", IsoChronology.INSTANCE.date(1990, 7, 15), OtherPerson.Sex.MALE, "mark@example.com"));
members.add(new OtherPerson("George", IsoChronology.INSTANCE.date(1991, 8, 13), OtherPerson.Sex.MALE, "george@example.com"));
members.add(new OtherPerson("Bob", IsoChronology.INSTANCE.date(2000, 9, 12), OtherPerson.Sex.MALE, "bob@example.com"));

Map<Integer, List<Person>> collect = members.stream().collect(groupingBy(Person::getAge));

Map<Integer, List<String>> result = new HashMap<>();

collect.keySet().forEach(key -> {
            result.put(key, collect.get(key).stream().map(Person::getName).collect(toList()));
});

当前解决方案

不理想,为了学习,我希望有一个更优雅和更好的解决方案。

Not ideal and for the sake of learning I'd like to have a more elegant and performing solution.

推荐答案

使用 Collectors.groupingBy ,你可以指定一个使用自定义收集器对值进行缩减操作。在这里,我们需要使用 Collectors.mapping ,它接受一个函数(映射是什么)和一个收集器(如何收集映射的值)。在这种情况下,映射是 Person :: getName ,即返回Person名称的方法引用,我们将其收集到 List

When grouping a Stream with Collectors.groupingBy, you can specify a reduction operation on the values with a custom Collector. Here, we need to use Collectors.mapping, which takes a function (what the mapping is) and a collector (how to collect the mapped values). In this case the mapping is Person::getName, i.e. a method reference that returns the name of the Person, and we collect that into a List.

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

这篇关于使用自定义收集器进行Java 8分组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆