标题:Java 中使用 Stream 和递归 Map 实现嵌套字符串的层级分组
发布时间 - 2026-01-28 00:00:00 点击率:次本文介绍如何将形如 "caso.id"、"caso.responsavel.dadospessoais.nome" 的点分隔字符串列表,递归构建为嵌套的 `map
在 Java 中,对点号(.)分隔的路径字符串进行层级化组织是常见需求,例如映射 DTO 字段路径、构建动态查询条件树或生成嵌套配置结构。Collectors.groupingBy() 虽强大,但仅支持单层分组;而本例需递归解析路径深度、动态创建嵌套 Map,无法通过标准 Stream 操作一步完成——必须结合递归逻辑与泛型 Map 构建。
核心思路是:将每个字符串按 . 拆分为路径节点数组(如 "caso.responsavel.dadosPessoais.nome" → ["caso", "responsavel", "dadosPessoais", "nome"]),再逐层下沉插入到嵌套 Map
- 叶子节点(最后一级)→ 实际无值,仅作占位(或可存 null/Boolean.TRUE 表示存在);
- 中间节点 → 指向子 Map
。
以下是完整可运行实现:
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);
}
print(root, "");
}
/**
* 递归填充嵌套 Map:从 index 开始,将 nodes[index..end] 插入到 map 中
*/
public static void fill(Map map, String[] nodes, int index) {
if (index >= nodes.length) return;
String key = nodes[index];
Object existing = map.get(key);
if (existing == null) {
// 当前层级不存在 → 创建新子 Map 并挂载
Map childMap = new HashMap<>();
map.put(key, childMap);
fill(childMap, nodes, index + 1); // 继续向下构建
} else if (existing instanceof Map) {
// 已存在子 Map → 递归插入到该子 Map
@SuppressWarnings("unchecked")
Map childMap = (Map) existing;
fill(childMap, nodes, index + 1);
}
// 若 existing 非 Map(如意外覆盖),此处可抛异常或忽略(本例中不会发生)
}
/**
* 树状打印 Map,缩进表示层级深度
*/
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 + " ");
}
}
}
} ✅ 输出效果(缩进清晰体现层级关系):
caso
id
unidadeDoCaso
id
etiqueta
sigiloso
idPecaSegredoJustica
numeroAno
numero
competencia
id
ativo
nome
responsavel
id
dadosPessoais
nome
escrivao
id
dadosPessoais
nome⚠️ 注意事项:
-
类型安全:Map
是运行时泛型擦除后的折中方案;若需编译期强约束,可封装为 NestedPathTree 自定义类,提供 add(String path) 和 getChildren(String... ancestors) 等方法。 - 重复路径处理:当前 fill() 对重复路径(如两次 "caso.id")静默忽略,如需校验可添加 if (index == nodes.length - 1 && existing != null) 报警逻辑。
- 空节点防御:生产环境建议在 split() 后过滤空字符串(Arrays.stream(nodes).filter(s -> !s.isBlank()).toArray(String[]::new)),避免 "a..b" 导致异常。
- 性能考量:对于超大规模路径集(>10 万条),可考虑用 Trie 或 ConcurrentHashMap 优化并发插入,但本方案已满足绝大多数元数据建模场景。
该模式本质是轻量级路径字典树(Path Trie)的 Map 实现,无需引入额外依赖,即可在纯 JDK 环境下完成灵活、可读、可扩展的嵌套结构构建。
# java
# js
# json
# node
# ai
# stream
# red
# String
# Boolean
# Object
# NULL
# if
# 封装
# Filter
# 字符串
# 递归
# Length
# 泛型
# map
# 并发
# 树状
# 本例
# 两种
# 两次
# 适用于
# 可在
# 不存在
# 自定义
# 如需
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何使用Vite进行前端资源打包?(配置示例)
Android自定义控件实现温度旋转按钮效果
如何快速上传建站程序避免常见错误?
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
如何在云虚拟主机上快速搭建个人网站?
百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭
车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?
怎样使用JSON进行数据交换_它有什么限制
如何彻底删除建站之星生成的Banner?
佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】
济南网站建设制作公司,室内设计网站一般都有哪些功能?
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
Laravel中的Facade(门面)到底是什么原理
黑客如何通过漏洞一步步攻陷网站服务器?
如何用花生壳三步快速搭建专属网站?
Windows Hello人脸识别突然无法使用
Laravel Docker环境搭建教程_Laravel Sail使用指南
Laravel怎么连接多个数据库_Laravel多数据库连接配置
Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】
Laravel Octane如何提升性能_使用Laravel Octane加速你的应用
海南网站制作公司有哪些,海口网是哪家的?
图册素材网站设计制作软件,图册的导出方式有几种?
Bootstrap CSS布局之列表
Laravel如何处理文件下载请求?(Response示例)
如何在建站之星绑定自定义域名?
深圳防火门网站制作公司,深圳中天明防火门怎么编码?
Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面
大学网站设计制作软件有哪些,如何将网站制作成自己app?
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
香港服务器部署网站为何提示未备案?
JavaScript Ajax实现异步通信
如何快速搭建安全的FTP站点?
Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势
Laravel如何记录自定义日志?(Log频道配置)
Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层
微信小程序制作网站有哪些,微信小程序需要做网站吗?
Laravel如何设置自定义的日志文件名_Laravel根据日期或用户ID生成动态日志【技巧】
HTML 中动态设置元素 name 属性的正确语法详解
laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法
Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程
Laravel如何使用Passport实现OAuth2?(完整配置步骤)
Laravel如何创建自定义Artisan命令?(代码示例)
Laravel怎么在Controller之外的地方验证数据
Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】
Laravel怎么上传文件_Laravel图片上传及存储配置
Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能
Laravel如何实现RSS订阅源功能_Laravel动态生成网站XML格式订阅内容【教程】
Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性
悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音


