0
public class Student {
    String name;
    int age;
}

我有一个Student对象列表,我需要根据特定逻辑对它们进行分组:

  1. 将姓名以“A”开头的所有学生分组
  2. 将姓名以“P”开头的所有学生分组
  3. 将所有年龄大于或等于 30 岁的学生分组

到目前为止,我做了什么:

List<Student> students = List.of(
     new Student("Alex", 31), 
     new Student("Peter", 33), 
     new Student("Antony", 32),
     new Student("Pope", 40), 
     new Student("Michel", 30));

Function<Student, String> checkFunction = e -> {
    if (e.getName().startsWith("A")) {
        return "A-List";
    } else if (e.getName().startsWith("P")) {
        return "P-List";
    } else if (e.getAge() >= 30) {
        return "30's-List";
    } else {
        return "Exception-List";
    }
};

Map<String, List<Student>> result = students.stream().collect(Collectors.groupingBy(checkFunction));

for (var entry : result.entrySet()) {
    System.out.println(entry.getKey() + "---");
    for (Student std : entry.getValue()) {
        System.out.println(std.getName());
    }
}

输出

A-List---
Alex
Antony
P-List---
Peter
Pope
30's-List---
Michel

我理解我所遵循的这个逻辑是错误的,这就是为什么 30 的列表没有正确填充的原因。真的有可能groupingBy()吗?

4

1 回答 1

1

这可以像在Java 8 group by String中一样处理,但您必须适应checkFunction实际返回 each 的组Student

private Stream<String> mapToGroups(Student e) {
    Builder<String> builder = Stream.builder();
    boolean isException = false;
    if (e.getName().startsWith("A")) {
        builder.add("A-List");
    } else if (e.getName().startsWith("P")) {
        builder.add("P-List");
    } else {
        isException = true;
    }
    if (e.getAge() >= 30) {
        builder.add("30's-List");
    } else if (isException) {
        builder.add("Exception-List");
    }
    return builder.build();
}

但是,如果我们在flatMap()调用中使用这个函数,我们会Student在这个过程中丢失。所以我们真正想要的是让这个方法返回String<Map.Entry<String, Student>>,以便我们以后可以使用分组的键和收集组的值:

private Stream<Entry<String, Student>> mapToGroupEntries(Student e) {
    Builder<Entry<String, Student>> builder = Stream.builder();
    boolean isException = false;
    if (e.getName().startsWith("A")) {
        builder.add(new SimpleEntry<>("A-List", e));
    } else if (e.getName().startsWith("P")) {
        builder.add(new SimpleEntry<>("P-List", e));
    } else {
        isException = true;
    }
    if (e.getAge() >= 30) {
        builder.add(new SimpleEntry<>("30's-List", e));
    } else if (isException) {
        builder.add(new SimpleEntry<>("Exception-List", e));
    }
    return builder.build();
}

我们现在可以使用此函数作为flatMap()调用的一部分,将我们转换Stream<Student>为 a Stream<Entry<String, Student>>,然后将它们分组:

Map<String, List<Student>> result = students.stream()
        .flatMap(s -> mapToGroupEntries(s))
        .collect(Collectors.groupingBy(Entry::getKey,
                Collectors.mapping(Entry::getValue, Collectors.toList())));
于 2022-01-26T18:06:28.487 回答