如何用Java Stream将含Object3列表的Object1集合转为Map<Object3,Object2>
问题描述
给定如下Object1类:
class Object1 { private Object2 object2; private List<Object3> object3s; // 假设存在对应的getter方法:getObject2()、getObject3s() }
以及一个List<Object1>集合accounts,当前通过如下循环方式创建Map<Object3, Object2>:
Map<Object3, Object2> accountMap = new HashMap<>(); for (Object1 dto : accounts) { dto.getObject3s() .forEach(obj3 -> accountMap.put(obj3, dto.getObject2())); }
请问如何使用Stream流更优雅地实现该Map的创建?
优化实现
可以通过Stream的flatMap展开每个Object1对应的Object3集合,结合Collectors.toMap构建目标Map,代码如下:
Map<Object3, Object2> accountMap = accounts.stream() .flatMap(obj1 -> obj1.getObject3s().stream() .map(obj3 -> new AbstractMap.SimpleEntry<>(obj3, obj1.getObject2()))) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> newValue // 重复key时保留新值,和原循环逻辑一致 ));
关键说明
flatMap:将每个Object1中的List<Object3>转为流,同时把每个Object3和对应的Object2包装成键值对(用AbstractMap.SimpleEntry临时存储),最终合并为一个包含所有键值对的流。Collectors.toMap:负责将流中的键值对收集为Map。第三个参数是重复键的合并策略,这里指定用新值覆盖旧值,和原循环中put方法的行为完全匹配(原循环中同一Object3多次出现时,后续的put会覆盖之前的映射)。
如果使用Java 9及以上版本,还可以用更简洁的Map.entry()静态方法替代AbstractMap.SimpleEntry:
Map<Object3, Object2> accountMap = accounts.stream() .flatMap(obj1 -> obj1.getObject3s().stream() .map(obj3 -> Map.entry(obj3, obj1.getObject2()))) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldVal, newVal) -> newVal ));
内容的提问来源于stack exchange,提问作者user3103115
相关产品推荐
相关产品推荐

