如何用单语句将List<Definition>转为Map<String, Map<String, Definition>>?
问题:将List转换为嵌套Map的单语句实现
需求:已将对象数组转为List<Definition>,需要转换为Map<String, Map<String, Definition>>,外层Map的键为defName,内层Map的键为defDesc,且同一defName下的defDesc唯一。
原始对象数组:
[ { "defName": "Project", "defDesc": "Project 1", "defID": "abcd123", "defClass": "class1" }, { "defName": "Project", "defDesc": "Project 2", "defID": "asdoihw1345", "defClass": "class2" }, { "defName": "Project", "defDesc": "Project 3", "defID": "ewrwu123", "defClass": "class3" }, { "defName": "Product", "defDesc": "Product 1", "defID": "pgkorejgoi1234", "defClass": "class1" }, { "defName": "Product", "defDesc": "Product 2", "defID": "asadsad2343", "defClass": "class2" }, { "defName": "Product", "defDesc": "Product 3", "defID": "4dgaksld", "defClass": "class3" } ]
原有两步实现:
List<Definition> definitions = // 从JSON获取的列表 Map<String, List<Definition>> definitionByName = definitions.stream().collect(Collectors.groupingBy(Definition::getDefName)); Map<String, Map<String, Definition>> definitionMap = new HashMap<>(); definitionByName.forEach((name, definitionList) -> { Map<String, Definition> definitionDescMap = definitionList.stream() .collect(Collectors.toMap(def -> def.getDefDesc(), Function.identity())); definitionMap.put(name, definitionDescMap); });
Java 8 单语句解决方案
可以直接使用Collectors.groupingBy的重载方法,指定下游收集器为Collectors.toMap,一步完成嵌套Map的转换:
List<Definition> definitions = // 从JSON获取的列表 Map<String, Map<String, Definition>> definitionMap = definitions.stream() .collect(Collectors.groupingBy( Definition::getDefName, Collectors.toMap(Definition::getDefDesc, Function.identity()) ));
说明
- 第一个参数
Definition::getDefName是外层Map的分组键提取函数; - 第二个参数是下游收集器,将每个分组内的
List<Definition>直接转换为以defDesc为键、Definition对象为值的内层Map; - 由于你明确同一
defName下的defDesc唯一,无需处理键冲突,所以不用额外指定冲突合并函数。
Java 8+ 优化参考
如果后续使用Java 16及以上版本,写法逻辑和Java 8一致,但可以根据场景补充冲突处理逻辑(比如出现defDesc重复时):
Map<String, Map<String, Definition>> definitionMap = definitions.stream() .collect(Collectors.groupingBy( Definition::getDefName, Collectors.toMap( Definition::getDefDesc, Function.identity(), (existing, replacement) -> replacement // 冲突时保留新对象 ) ));
内容的提问来源于stack exchange,提问作者iCode
相关产品推荐
相关产品推荐

