
本文介绍如何通过递归遍历任意深度的嵌套人员数据(含 name、age、children),将其转换为结构一致的 Person 对象树,确保每个节点的 children 字段正确引用其子节点列表。
本文介绍如何通过递归遍历任意深度的嵌套人员数据(含 name、age、children),将其转换为结构一致的 `person` 对象树,确保每个节点的 `children` 字段正确引用其子节点列表。
在处理具有层级关系的嵌套数据(如家谱、组织架构或评论回复链)时,Java 中最自然且可靠的建模方式是递归构造对象树。核心思想是:对每个 Person 实例,先创建自身,再对其 children 字段递归调用相同逻辑——即“创建当前节点 → 递归构建子树 → 组装父子关系”。
以下是一个完整、可直接落地的实现方案:
✅ 定义清晰的 Person 模型类
static class Person {
String name;
int age;
List<person> children;
// 无子节点构造器
Person(String name, int age) {
this.name = name;
this.age = age;
this.children = null; // 显式设为 null,语义更清晰
}
// 带子节点构造器(推荐用于反序列化)
Person(String name, int age, List<person> children) {
this.name = name;
this.age = age;
this.children = children;
}
}</person></person>
⚠️ 注意:children 字段应允许为 null(表示无子节点),而非空 List —— 这能准确反映原始数据语义,并避免冗余对象创建。
Java JDK 25下载Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
✅ 递归构建方法(关键逻辑)
// 全局容器:存储所有已构建的 Person 实例(按需保留)
private final List<person> allPersons = new ArrayList();
/**
* 递归遍历并构建 Person 树
* @param persons 当前层级的 Person 列表(可能为空或 null)
*/
private void buildPersonTree(List<person> persons) {
if (persons == null || persons.isEmpty()) return;
for (Person person : persons) {
// 1. 将当前 person 加入全局列表(如需扁平化访问)
allPersons.add(person);
// 2. 递归构建其子树
if (person.children != null) {
buildPersonTree(person.children);
}
}
}</person></person>
✅ 在 API 回调中集成构建流程
private void loadPersons(String id) {
ListPersonsApi.Request request = Jso.create();
request.id = id;
dispatcher.send(ListPersonsApi.PATH, request, r -> {
// 步骤1:将原始 API 数据映射为 Person 对象树(保持嵌套结构)
List<person> rootPersons = new ArrayList();
for (ListPersonsApi.Person apiPerson : r.persons) {
// 递归转换 children 字段(关键!)
List<person> convertedChildren = convertChildren(apiPerson.children);
rootPersons.add(new Person(apiPerson.name, apiPerson.age, convertedChildren));
}
// 步骤2:启动递归构建,填充 allPersons 并建立完整树形关系
buildPersonTree(rootPersons);
});
}
// 辅助方法:将 API 的 children 数组递归转为 Person 列表
private List<person> convertChildren(List<listpersonsapi.person> apiChildren) {
if (apiChildren == null || apiChildren.isEmpty()) return null;
List<person> children = new ArrayList();
for (ListPersonsApi.Person child : apiChildren) {
List<person> grandChildren = convertChildren(child.children);
children.add(new Person(child.name, child.age, grandChildren));
}
return children;
}</person></person></listpersonsapi.person></person></person></person>
✅ 使用示例与验证
假设 API 返回如下 JSON 结构:
{
"persons": [
{"name":"John","age":18,"children":null},
{"name":"Lisa","age":32,"children":[{"name":"Tyler","age":7,"children":null}]},
{"name":"Mike","age":90,"children":[{"name":"Derek","age":50,"children":[{"name":"Mary","age":25,"children":null},{"name":"Beth","age":16,"children":null}]}]}]
}
执行后,allPersons 将包含 7 个 Person 实例,且 Mike.children.get(0).children 正确指向包含 Mary 和 Beth 的列表,形成完整树形引用链。
? 关键注意事项
- 避免循环引用:确保原始数据无环(如 A 的孩子是 B,B 的孩子又包含 A),否则递归会栈溢出;
- 空值防御:始终检查 children == null 而非 children.isEmpty(),因 null 表示“无子节点”,空列表则表示“有子节点但为空”;
- 内存考量:若仅需树形结构而无需扁平列表,可移除 allPersons,直接返回根节点列表;
- 性能提示:对于超深嵌套(>1000 层),考虑改用栈模拟递归以防 StackOverflowError,但日常业务场景中递归完全足够。
通过这一设计,你获得了可读性强、扩展性好、且与原始数据结构严格对齐的领域模型,为后续渲染、搜索或编辑提供了坚实基础。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











