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

如何从Child树形结构生成CustomChild路径列表?

问题描述

我定义了如下Child类:

public class Child {
    private String id;
    private List<Child> children;
    // 省略getter、setter和构造方法
}

对应的JSON树形结构示例:

{
    "id": "1",
    "children": [
        {
            "id": "1_1",
            "children": [
                {
                    "id": "1_1_1"
                },{
                    "id": "1_1_2",
                    "children": [
                        {
                            "id": "1_1_2_1"
                        }
                    ]
                }
            ]
        },{
            "id": "1_2",
            "children": [
                {
                    "id": "1_2_1",
                    "children": [
                        {
                            "id": "1_2_1_1"
                        }
                    ]
                }
            ]
        }
    ]
}

希望获取该树形结构的所有根到叶子节点的完整路径,将每条路径转换为CustomChild类型的对象,最终组成列表。CustomChild类定义:

public class CustomChild {
    private String id;
    private CustomChild child;
    // 省略getter、setter和构造方法
}

期望输出列表示例:

[
    {
        "id":"1",
        "child": {
            "id": "1_1",
            "child": {
                "id": "1_1_1"
            }
        }
    },
    {
        "id":"1",
        "child": {
            "id": "1_1",
            "child": {
                "id": "1_1_2",
                "child": {
                    "id": "1_1_2_1"
                }
            }
        }
    },
    {
        "id":"1",
        "child": {
            "id": "1_2",
            "child": {
                "id": "1_2_1",
                "child": {
                    "id": "1_2_1_1"
                }
            }
        }
    }
]

尝试递归实现但未成功,求可行方案。

解决方案

核心思路是通过深度优先遍历树形结构,记录每条从根到叶子的路径,再将路径转换为CustomChild的链式结构。

实现步骤

  • 递归遍历每个节点,维护当前路径的节点列表;
  • 当遍历到叶子节点(无子节点或子节点列表为空)时,将当前路径转换为CustomChild链式对象,加入结果列表;
  • 非叶子节点则继续递归遍历其所有子节点,遍历完成后回溯路径,确保路径始终对应当前递归层级的节点链。

代码实现

import java.util.ArrayList;
import java.util.List;

public class TreeConverter {

    // 转换入口方法
    public static List<CustomChild> convertToCustomChildList(Child root) {
        List<CustomChild> result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        List<Child> currentPath = new ArrayList<>();
        currentPath.add(root);
        traverse(root, currentPath, result);
        return result;
    }

    // 递归遍历方法
    private static void traverse(Child node, List<Child> currentPath, List<CustomChild> result) {
        List<Child> children = node.getChildren();
        // 叶子节点:转换路径为CustomChild并加入结果
        if (children == null || children.isEmpty()) {
            result.add(convertPathToCustomChild(currentPath));
            return;
        }
        // 非叶子节点:遍历所有子节点
        for (Child child : children) {
            currentPath.add(child);
            traverse(child, currentPath, result);
            // 回溯:移除当前子节点,回到父节点路径
            currentPath.remove(currentPath.size() - 1);
        }
    }

    // 将路径列表转换为CustomChild链式结构
    private static CustomChild convertPathToCustomChild(List<Child> path) {
        CustomChild prev = null;
        // 从路径末尾(叶子节点)往前构建链式结构,逻辑更简洁
        for (int i = path.size() - 1; i >= 0; i--) {
            Child childNode = path.get(i);
            CustomChild custom = new CustomChild();
            custom.setId(childNode.getId());
            custom.setChild(prev);
            prev = custom;
        }
        return prev;
    }

    // Child类的getter/setter实现
    static class Child {
        private String id;
        private List<Child> children;

        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        public List<Child> getChildren() { return children; }
        public void setChildren(List<Child> children) { this.children = children; }
    }

    // CustomChild类的getter/setter实现
    static class CustomChild {
        private String id;
        private CustomChild child;

        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        public CustomChild getChild() { return child; }
        public void setChild(CustomChild child) { this.child = child; }
    }

    // 测试示例
    public static void main(String[] args) {
        // 构建示例树形结构
        Child leaf1_1_1 = new Child();
        leaf1_1_1.setId("1_1_1");

        Child leaf1_1_2_1 = new Child();
        leaf1_1_2_1.setId("1_1_2_1");

        Child node1_1_2 = new Child();
        node1_1_2.setId("1_1_2");
        node1_1_2.setChildren(List.of(leaf1_1_2_1));

        Child node1_1 = new Child();
        node1_1.setId("1_1");
        node1_1.setChildren(List.of(leaf1_1_1, node1_1_2));

        Child leaf1_2_1_1 = new Child();
        leaf1_2_1_1.setId("1_2_1_1");

        Child node1_2_1 = new Child();
        node1_2_1.setId("1_2_1");
        node1_2_1.setChildren(List.of(leaf1_2_1_1));

        Child node1_2 = new Child();
        node1_2.setId("1_2");
        node1_2.setChildren(List.of(node1_2_1));

        Child root = new Child();
        root.setId("1");
        root.setChildren(List.of(node1_1, node1_2));

        // 转换并验证结果
        List<CustomChild> result = convertToCustomChildList(root);
        // 可通过Jackson等JSON工具将result转为JSON,结果与期望一致
    }
}

关键说明

  • 回溯机制:遍历子节点后必须从当前路径中移除该节点,否则路径会包含无关节点,导致转换结果错误;
  • 反向构建链式结构:从叶子节点往根节点反向创建CustomChild对象,只需将前一个节点设为当前节点的child,逻辑简单不易出错;
  • 空值处理:判断叶子节点时同时考虑children为null或空列表的情况,避免空指针异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:02:51