簡體   English   中英

使用自定義收集器的 Java 8 分組?

[英]Java 8 grouping using custom collector?

我有以下課程。

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表達中。

為了簡化所有這些,我鏈接了我當前的解決方案,該解決方案存儲按年齡分組的結果,然后對其進行迭代以收集名稱。

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

當前解決方案

不理想,為了學習,我想要一個更優雅和更高效的解決方案。

使用Collectors.groupingBy對 Stream 進行分組時,您可以使用自定義Collector指定對值的歸約操作。 在這里,我們需要使用Collectors.mapping ,它接受一個函數(映射是什么)和一個收集器(如何收集映射值)。 在這種情況下,映射是Person::getName ,即返回 Person 名稱的方法引用,我們將其收集到List

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

您可以使用mapping CollectorPerson列表mappingPerson列表:

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

您還可以使用 Collectors.toMap 並提供鍵、值和合並函數(如果有)的映射。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM