如何用Java 8 Stream高效将键值对转换为按键分组的对象Map
最优实现:一次流处理完成转换
嘿,我来帮你把这个转换逻辑优化到最简洁高效!你之前的思路需要两次流处理,其实我们可以用Collectors.toMap直接在一次遍历里完成所有操作,既减少了中间集合的创建,又避免了额外的流遍历开销,这应该是最快的实现方式了。
代码实现
假设你的AgencyInfo类有对应的setter方法,直接用下面的代码:
List<AgencyMapping> agencyMappings; // 你的原始列表 Map<Integer, AgencyInfo> agencyInfoByAgencyId = agencyMappings.stream() .collect(Collectors.toMap( // 键:取AgencyMapping的agencyId AgencyMapping::getAgencyId, // 值:将单个AgencyMapping转换为AgencyInfo mapping -> { AgencyInfo info = new AgencyInfo(); info.setAgencyId(mapping.getAgencyId()); Set<String> scoreKeys = new HashSet<>(); scoreKeys.add(mapping.getScoreKey()); info.setScoreKeys(scoreKeys); return info; }, // 合并逻辑:当同一个agencyId出现多次时,合并scoreKeys集合 (existingInfo, newInfo) -> { existingInfo.getScoreKeys().addAll(newInfo.getScoreKeys()); return existingInfo; } ));
简化版(如果AgencyInfo有构造函数)
如果能给AgencyInfo加一个构造函数:
public class AgencyInfo { private Integer agencyId; private Set<String> scoreKeys; public AgencyInfo(Integer agencyId, Set<String> scoreKeys) { this.agencyId = agencyId; this.scoreKeys = scoreKeys; } // 原有的getter/setter }
那代码可以更简洁:
Map<Integer, AgencyInfo> agencyInfoByAgencyId = agencyMappings.stream() .collect(Collectors.toMap( AgencyMapping::getAgencyId, m -> new AgencyInfo(m.getAgencyId(), new HashSet<>(Collections.singleton(m.getScoreKey()))), (info1, info2) -> { info1.getScoreKeys().addAll(info2.getScoreKeys()); return info1; } ));
为什么这是最快的?
- 一次遍历完成:只需要遍历原始
agencyMappings列表一次,在收集过程中直接构建并合并AgencyInfo对象,避免了二次遍历entrySet的开销。 - 减少中间对象:不需要先生成
Map<Integer, Set<String>>这种中间集合,直接操作目标对象,内存和性能开销都更小。
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

