Java 8 Collectors groupingBy:将含重复名称的Person列表转为GroupedPersons列表
解决方案:用组合式Collector直接完成转换
当然可以!你完全可以通过一个组合式Collector实现这个需求,不需要手动创建中间映射变量,也不用额外的辅助类——只需要利用Java Stream提供的Collectors.collectingAndThen结合groupingBy来完成分组到结果列表的无缝转换。
先明确前提类结构
假设你的实体类是这样的(如果结构不同,只需要调整对应的getter或构造方法即可):
// Person类,包含名称属性 class Person { private String name; public Person(String name) { this.name = name; } public String getName() { return name; } } // 目标GroupedPersons类,包含名称和同名Person列表 class GroupedPersons { private String name; private List<Person> persons; public GroupedPersons(String name, List<Person> persons) { this.name = name; this.persons = persons; } // 可选:添加toString方便调试 @Override public String toString() { return "GroupedPersons{name='" + name + "', persons=" + persons + '}'; } }
核心实现代码
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class GroupingExample { public static void main(String[] args) { List<Person> personList = Arrays.asList( new Person("Alice"), new Person("Bob"), new Person("Alice"), new Person("Charlie"), new Person("Bob") ); // 关键:用一个Collector直接收集成List<GroupedPersons> List<GroupedPersons> groupedPersons = personList.stream() .collect(Collectors.collectingAndThen( // 第一步:按名称分组,得到Map<String, List<Person>> Collectors.groupingBy(Person::getName), // 第二步:将分组后的Map转换为目标列表 groupedMap -> groupedMap.entrySet().stream() .map(entry -> new GroupedPersons(entry.getKey(), entry.getValue())) .collect(Collectors.toList()) )); // 打印结果验证 groupedPersons.forEach(System.out::println); } }
为什么这符合需求?
- 仅用一个Collector:
collectingAndThen本身就是一个Collector,它包装了groupingBy这个Collector,并对分组后的结果做最终转换——整个collect方法只接收这一个组合式Collector实例。 - 无中间映射变量:分组得到的Map完全在Collector内部处理,不需要你手动声明或操作这个Map变量。
- 无额外类:只用到了你已经定义的
Person和GroupedPersons,没有新增任何辅助类。
扩展:如果需要保持分组顺序?
如果希望输出的GroupedPersons列表保持原列表中名称首次出现的顺序,可以把groupingBy换成带有序Map的重载版本:
Collectors.groupingBy(Person::getName, LinkedHashMap::new, Collectors.toList())
这样分组后的Map会保留插入顺序,转换后的列表也会对应保持顺序。
内容的提问来源于stack exchange,提问作者danial
相关产品推荐
相关产品推荐

