
本文介绍如何使用 java 递归 + hashmap 构建嵌套层级结构,将点号分隔的字符串(如 "caso.responsavel.dadospessoais.nome")自动解析并组织为多级 map 树,支持任意深度嵌套,适用于动态字段路径建模场景。
在 Java 中,Collectors.groupingBy() 虽强大,但仅适用于单层分组;而面对类似 "caso.competencia.nome" 这类含多级路径的字符串,需构建树状嵌套映射(Tree-like Map),即每个节点既是键,又可作为子 Map 的容器。这无法通过标准 Stream API 直接完成,但可通过递归填充 + 泛型 Map 嵌套优雅实现。
核心思路
将每个字符串按 . 拆分为路径数组(如 "caso.responsavel.dadosPessoais.nome" → ["caso", "responsavel", "dadosPessoais", "nome"]),再逐级下沉插入到嵌套 Map
- Object 类型允许值为 String(叶子节点)或 Map
(中间节点); - 递归函数 fill() 负责从指定层级开始,确保路径上每级键存在且为 Map,最终在末尾插入占位(实际业务中可替换为真实值);
- print() 函数则以缩进形式可视化树结构,便于调试。
完整可运行示例
import java.util.*;
public class NestedStringGrouping {
public static void main(String[] args) {
String[] array = {
"caso.id", "caso.unidadeDoCaso.id", "caso.etiqueta",
"caso.sigiloso", "caso.idPecaSegredoJustica", "caso.numeroAno",
"caso.numero", "caso.competencia.id", "caso.competencia.ativo",
"caso.competencia.nome", "caso.responsavel.id",
"caso.responsavel.dadosPessoais.nome", "caso.escrivao.id",
"caso.escrivao.dadosPessoais.nome"
};
Map root = new HashMap<>();
for (String path : array) {
String[] nodes = path.split("\\.");
fill(root, nodes, 0);
}
System.out.println("Nested structure:");
print(root, "");
}
// 递归填充:将 nodes[i..end] 路径插入到 map 中
public static void fill(Map map, String[] nodes, int i) {
if (i >= nodes.length) return;
String key = nodes[i];
Object existing = map.get(key);
if (existing == null) {
// 当前层级不存在 → 创建新子 Map 并挂载
Map subMap = new HashMap<>();
map.put(key, subMap);
fill(subMap, nodes, i + 1); // 继续向下构建
} else if (existing instanceof Map) {
// 已存在子 Map → 继续递归填充
@SuppressWarnings("unchecked")
Map subMap = (Map) existing;
fill(subMap, nodes, i + 1);
}
// 若 existing 非 Map(如已存为 String),此处可抛异常或覆盖逻辑(本例仅建结构,无需值)
}
// 递归打印:缩进显示层级关系
public static void print(Map map, String indent) {
for (String key : map.keySet()) {
System.out.println(indent + key);
Object value = map.get(key);
if (value instanceof Map) {
print((Map) value, indent + " ");
}
}
}
} 关键注意事项
- ✅ 类型安全提示:Map
是必要妥协,实际项目中建议封装为 NestedPathMap 类,隐藏强制转换细节; - ⚠️ 叶子节点无值:当前实现仅构建结构(所有叶子为 null 或空 Map)。若需存储原始字符串或关联数据,可在 i == nodes.length - 1 时 map.put(key, path);
- ? 避免重复路径:若输入含重复路径(如两次 "caso.id"),第二次 fill() 将静默跳过 —— 可根据需求改为抛异常或计数;
- ? 扩展性:该模式可轻松适配 JSON Schema 生成、动态表单字段分组、权限路径树等场景。
总结
虽然 Java Stream 不直接支持“递归 groupingBy”,但结合 split()、HashMap 和简洁递归,我们能以不到 30 行核心逻辑实现任意深度的嵌套字符串分组。它不依赖第三方库,语义清晰,且易于单元测试与定制 —— 是处理动态路径建模的经典轻量方案。










