You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 8 Streams三级以上分组:生成指定嵌套Map结构

用Java 8 Stream实现指定嵌套Map结构

需求回顾

需要将包含编码类型、新旧长短编码的对象列表,转换成如下嵌套结构的Map(对应示例JSON):
外层以account为键,内层按codetype分组,每个编码类型下包含OLD和NEW两个节点,分别存储对应长短编码。

原代码问题分析

你提供的代码存在以下核心问题:

  • 仅处理了OLD节点,未生成NEW节点,无法满足完整结构需求
  • 使用groupingBy配合toList,导致最终结构包含列表,但目标结构中每个OLD/NEW是单个对象而非列表
  • 泛型定义与目标结构不匹配,引入了不必要的List<Object>层级

正确实现方案

方案1:自定义类型实现(类型安全)

先定义对应结构的实体类,再通过Stream的toMap完成转换:

// 假设已有实体类GetCodeTypes(包含对应getter方法)
class GetCodeTypes {
    private String codetype;
    private String shortOldCode;
    private String longOldCode;
    private String shortNewCode;
    private String longNewCode;

    // getter方法
    public String getCodetype() { return codetype; }
    public String getShortOldCode() { return shortOldCode; }
    public String getLongOldCode() { return longOldCode; }
    public String getShortNewCode() { return shortNewCode; }
    public String getLongNewCode() { return longNewCode; }
}

// 定义长短编码对的实体类
class CodePair {
    private String shortCode;
    private String longCode;

    public CodePair(String shortCode, String longCode) {
        this.shortCode = shortCode;
        this.longCode = longCode;
    }

    // getter方法(序列化需要)
    public String getShort() { return shortCode; }
    public String getLong() { return longCode; }
}

// 定义单个编码类型的OLD/NEW结构
class CodeTypeEntry {
    private CodePair OLD;
    private CodePair NEW;

    public CodeTypeEntry(CodePair oldPair, CodePair newPair) {
        this.OLD = oldPair;
        this.NEW = newPair;
    }

    public CodePair getOLD() { return OLD; }
    public CodePair getNEW() { return NEW; }
}

核心转换代码:

List<GetCodeTypes> dataMap = // 你的对象列表

// 按codetype分组,生成每个编码类型对应的OLD/NEW结构
Map<String, CodeTypeEntry> codeTypeMap = dataMap.stream()
        .collect(Collectors.toMap(
                GetCodeTypes::getCodetype,
                code -> {
                    CodePair oldPair = new CodePair(code.getShortOldCode(), code.getLongOldCode());
                    CodePair newPair = new CodePair(code.getShortNewCode(), code.getLongNewCode());
                    return new CodeTypeEntry(oldPair, newPair);
                },
                // 处理重复codetype的情况,这里保留已有值,可根据需求调整
                (existing, replacement) -> existing
        ));

// 包装到外层account键下
Map<String, Map<String, CodeTypeEntry>> finalResult = new HashMap<>();
finalResult.put("account", codeTypeMap);

方案2:纯Map嵌套实现(无需自定义类)

如果不想新增实体类,可直接用嵌套Map完成转换:

List<GetCodeTypes> dataMap = // 你的对象列表

Map<String, Map<String, Map<String, Map<String, String>>>> finalResult = new HashMap<>();

Map<String, Map<String, Map<String, String>>> codeTypeMap = dataMap.stream()
        .collect(Collectors.toMap(
                GetCodeTypes::getCodetype,
                code -> {
                    // 构建OLD节点
                    Map<String, String> oldMap = new HashMap<>();
                    oldMap.put("short", code.getShortOldCode());
                    oldMap.put("long", code.getLongOldCode());

                    // 构建NEW节点
                    Map<String, String> newMap = new HashMap<>();
                    newMap.put("short", code.getShortNewCode());
                    newMap.put("long", code.getLongNewCode());

                    // 组装OLD/NEW到当前编码类型节点
                    Map<String, Map<String, String>> oldNewMap = new HashMap<>();
                    oldNewMap.put("OLD", oldMap);
                    oldNewMap.put("NEW", newMap);

                    return oldNewMap;
                },
                (existing, replacement) -> existing
        ));

finalResult.put("account", codeTypeMap);

关键思路说明

  • 使用Collectors.toMap而非groupingBy:因为每个codetype对应唯一的一组OLD/NEW数据,toMap更适合这种键值一一对应的场景
  • 一次性完成单个对象到OLD/NEW结构的转换:在toMap的value生成器中直接构建目标结构,避免多层嵌套收集器的复杂逻辑

内容的提问来源于stack exchange,提问作者CodeFromSverige

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 10:32:24