如何通过单次Stream将自定义对象多String属性收集为Map<String,List<String>>
实现方案
可以通过单次流操作实现需求,核心思路是先把每个TeamMates实例拆解为「属性名-属性值」的键值对流,再通过Collectors.groupingBy聚合即可,不需要多次遍历集合,也不需要手动用forEach操作容器。
固定属性场景(推荐,性能更稳定)
如果TeamMates的属性固定,直接硬编码属性名即可:
import java.util.AbstractMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; // 你的业务逻辑 List<TeamMates> teamMatesList = ...; // 源数据列表 Map<String, List<String>> result = teamMatesList.stream() // 把每个对象拆为3个属性键值对,展开为流 .flatMap(teamMate -> List.of( new AbstractMap.SimpleEntry<>("playerFirstName", teamMate.getPlayerFirstName()), new AbstractMap.SimpleEntry<>("playerLastName", teamMate.getPlayerLastName()), new AbstractMap.SimpleEntry<>("playerMaidenName", teamMate.getPlayerMaidenName()) ).stream()) // 按属性名分组,收集对应属性值到列表 .collect(Collectors.groupingBy( Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList()) ));
如果你使用Java 9及以上版本,可以用Map.entry()替代AbstractMap.SimpleEntry,代码更简洁:
.flatMap(teamMate -> List.of( Map.entry("playerFirstName", teamMate.getPlayerFirstName()), Map.entry("playerLastName", teamMate.getPlayerLastName()), Map.entry("playerMaidenName", teamMate.getPlayerMaidenName()) ).stream())
动态属性场景
如果后续会频繁新增String类型的属性,不想每次修改硬编码的键值对列表,可以用反射动态读取所有String属性:
import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; List<TeamMates> teamMatesList = ...; Map<String, List<String>> result = teamMatesList.stream() .flatMap(teamMate -> Arrays.stream(TeamMates.class.getDeclaredFields()) // 只筛选String类型的属性 .filter(field -> field.getType() == String.class) // 开启私有属性访问权限 .peek(field -> field.setAccessible(true)) .map(field -> { try { return new AbstractMap.SimpleEntry<>(field.getName(), (String) field.get(teamMate)); } catch (IllegalAccessException e) { throw new RuntimeException(e); } }) ) .collect(Collectors.groupingBy( Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList()) ));
注意反射方案存在一定性能损耗,且如果类的属性有访问控制限制可能抛出异常,属性固定的场景优先选择硬编码方案。
内容的提问来源于stack exchange,提问作者Vijay Manohar
相关产品推荐
相关产品推荐

