如何用Lambda表达式重构数据结构:将<String, List<A>>转为<F, E>
如何将嵌套对象的Map重构为<F, E>类型的Map
嘿,这个问题其实就是把嵌套的对象层级一步步展开,最终建立起D的属性F和对应C的属性E的映射关系对吧?我给你拆解清楚,再附上代码示例~
首先先明确咱们的对象结构(用Java代码定义,方便理解):
class A { private List<B> bList; // 省略构造器、getter和setter方法 } class B { private C c; private D d; // 省略构造器、getter和setter方法 } class C { private String e; // 省略构造器、getter和setter方法 } class D { private Integer f; // 省略构造器、getter和setter方法 }
核心思路就是逐层遍历嵌套的集合,提取需要的属性并建立映射,下面给你两种常用的实现方式:
方式一:传统循环实现
这种方式逻辑直观,适合新手理解:
// 假设这是给定的原始Map Map<String, List<A>> originalMap = new HashMap<>(); // 初始化目标Map Map<Integer, String> targetMap = new HashMap<>(); // 遍历原始Map的所有值(所有A的列表) for (List<A> aList : originalMap.values()) { // 遍历每个A对象 for (A a : aList) { // 遍历A中的每个B对象 for (B b : a.getBList()) { // 提取C的E属性和D的F属性 String eValue = b.getC().getE(); Integer fValue = b.getD().getF(); // 存入目标Map targetMap.put(fValue, eValue); } } }
方式二:Stream API实现(Java 8+)
这种方式更简洁,代码可读性高,适合熟悉Stream的开发者:
Map<Integer, String> targetMap = originalMap.values().stream() // 把所有List<A>展开为单个A对象 .flatMap(Collection::stream) // 把每个A中的List<B>展开为单个B对象 .flatMap(a -> a.getBList().stream()) // 收集为目标Map,指定key、value和重复key的合并策略 .collect(Collectors.toMap( b -> b.getD().getF(), // key:D的F属性 b -> b.getC().getE(), // value:C的E属性 (existingVal, newVal) -> newVal // 重复key时,用新值覆盖旧值 ));
重要注意点
因为C和D是一对多关系,可能会出现多个D对象拥有相同的F属性值的情况:
- 如果用上面的代码,重复的F会被后面的覆盖,最终每个F只保留最后一个对应的E
- 如果你想保留所有对应同一个F的E值,可以把目标Map改为
Map<Integer, List<String>>,用分组收集:
Map<Integer, List<String>> targetMapWithAllValues = originalMap.values().stream() .flatMap(Collection::stream) .flatMap(a -> a.getBList().stream()) .collect(Collectors.groupingBy( b -> b.getD().getF(), Collectors.mapping(b -> b.getC().getE(), Collectors.toList()) ));
内容的提问来源于stack exchange,提问作者roland luo
相关产品推荐
相关产品推荐

