当前位置: 首页 > 知识库问答 >
问题:

使用自定义收集器的Java8分组?

郑茂勋
2023-03-14

我有以下课程。

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

我希望能够按年龄分组,然后收集人名列表,而不是人名对象本身;所有这些都在一个漂亮的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()));
});

当前解决方案

不理想,为了学习,我想有一个更优雅、更高效的解决方案。

共有3个答案

丁承德
2023-03-14

也可以使用收集器。toMap并为键、值和合并函数(如果有)提供映射。

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

您可以使用映射收集器人员列表映射到人员姓名列表:

Map<Integer, List<String>> collect = 
    members.stream()
           .collect(Collectors.groupingBy(Person::getAge,
                                          Collectors.mapping(Person::getName, Collectors.toList())));
公冶宏深
2023-03-14

使用收集器对流进行分组时。groupingBy,您可以使用自定义收集器指定值的缩减操作。在这里,我们需要使用收集器。映射,它包含一个函数(映射是什么)和一个收集器(如何收集映射值)。在这种情况下,映射是Person::getName,即返回人名的方法引用,我们将其收集到列表中。

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

 类似资料:
  • 问题内容: 我有以下课程。 我希望能够按年龄分组,然后收集人员名称列表,而不是人员对象本身。全部以一个漂亮的lamba表达式表示。 为了简化所有步骤,我链接了当前的解决方案,该解决方案按年龄存储分组的结果,然后对其进行迭代以收集名称。 当前解决方案 不理想,为了学习,我想有一个更优雅,更有效的解决方案。 问题答案: 将Stream与分组时,可以使用自定义对值指定归约运算。在这里,我们需要使用,它需

  • 我已经通过实现收集器接口并重写其方法实现了一个自定义收集器。收集器实现如下: 以下是我的Person类:

  • 我是使用Java8流API的新手,但我希望使用它来解决以下问题。假设我有一个名为的POJO,它包含、和属性,这些属性可以表示以下内容的每一行记录: 看起来如下: 上述四条记录需要合并为两条按名称分组的记录,其中: 属性求和 属性求和 组合记录包括属性,该属性是和的累加和相乘的结果。 因此,上述结果将是: 一个名为的不同POJO将表示组合记录的每一行记录: 有哪些好的方法/解决方案可以将输入的列表转

  • 问题内容: Java 8中有什么方法可以将一个元素分组而不收集它们?我希望结果再次出现。因为我必须处理大量数据甚至是无限流,所以我无法先收集数据并再次流处理结果。 所有需要分组的元素在第一流中都是连续的。因此,我喜欢使流评估保持懒惰。 问题答案: 无法使用标准Stream API做到这一点。通常,您无法执行此操作,因为将来总是有可能出现属于任何已创建组的新项目,因此,在处理所有输入之前,您无法将组

  • 在Java8中有什么方法可以在中分组元素而不收集它们吗?我希望结果再次成为。因为我必须处理大量的数据,甚至是无限的流,所以我不能首先收集数据,然后再次流化结果。 所有需要分组的元素在第一个流中是连续的。因此,我喜欢保持流评估懒惰。

  • Java流新手在这里。目前我正在完成本书中关于收集者的第6章(用流收集数据)。 我的对象是这样的。 这样做的目的是得到某种总体总结报告。基本上是一个HashMap 关键1: 投影-表示每个报告中所有投影的总和。 关键2: <代码>票据-表示每个报表中所有票据的总和。 关键3: 收入-表示每个报表的所有收入之和。 现在,我实际上通过创建自定义收集器来进行赋值,称为。 所以我得到的结果是这样的: 所以