如何用Java Stream按姓氏分组并提取用户名字段?
问题
我有一个List<Person>集合,可以通过Java Stream按姓氏分组,代码示例如下:
Map<String, List<Person>> persons.stream() .collect(Collectors.groupingBy(Person::getLastName));
但我希望按姓氏分组后得到对应的用户名单,例如姓氏为"Smith"时,对应["Jane","John"]。是否存在带值提取器的groupingBy()用法?我预想的代码如下:
Map<String, List<String>> persons.stream() .collect(Collectors.groupingBy(Person::getLastName, Person::getFirstName));
解决方案
你预想的写法不符合API规范,groupingBy的第二个参数需要传入一个Collector实现,而非直接的字段提取函数。要实现分组后提取指定字段的需求,需要结合Collectors.mapping()来完成——它负责将分组后的每个Person对象转换为目标字段值,再收集为列表。
正确实现代码如下:
Map<String, List<String>> groupedNames = persons.stream() .collect(Collectors.groupingBy( Person::getLastName, // 分组键:姓氏 Collectors.mapping( Person::getFirstName, // 值转换:提取名字 Collectors.toList() // 收集为列表 ) ));
代码说明
Person::getLastName:作为分组的键提取器,决定每个元素归属的分组;Collectors.mapping(Person::getFirstName, Collectors.toList()):作为分组的下游收集器,先将每个Person对象映射为名字字符串,再将这些字符串收集为List<String>,作为对应分组的值。
执行这段代码后,就能得到你期望的结构:键为姓氏字符串,值为对应姓氏下所有人的名字列表。
内容的提问来源于stack exchange,提问作者Garret Wilson
相关产品推荐
相关产品推荐

