Java树形结构案例怎么规整

wen java案例 33

本文目录导读:

Java树形结构案例怎么规整

  1. 核心数据模型设计
  2. 从平面列表构建树
  3. 树形数据的显示规整
  4. 完整案例:部门树
  5. 常用工具类库推荐
  6. 性能优化建议

针对Java树形结构数据的规整,核心在于数据建模递归处理展示格式化,以下是几种常见场景的规整方案和代码示例:

核心数据模型设计

首先需要一个通用的树节点基类:

public class TreeNode<T> {
    private T id;           // 节点ID
    private T parentId;     // 父节点ID
    private String name;    // 节点名称
    private List<TreeNode<T>> children; // 子节点列表
    // 扩展字段(可选)
    private Integer level;      // 层级
    private Boolean isLeaf;     // 是否叶子节点
    private String path;        // 节点路径
    public TreeNode() {
        this.children = new ArrayList<>();
    }
    // 省略getter/setter和构造函数
}

从平面列表构建树

这是最常见的场景:数据库查询出的扁平数据转换为树形结构。

两次遍历法(推荐)

public class TreeBuilder {
    public static <T> List<TreeNode<T>> buildTree(List<TreeNode<T>> flatList, T rootParentId) {
        List<TreeNode<T>> treeList = new ArrayList<>();
        // 1. 创建ID到节点的映射
        Map<T, TreeNode<T>> nodeMap = new HashMap<>();
        for (TreeNode<T> node : flatList) {
            nodeMap.put(node.getId(), node);
        }
        // 2. 构建父子关系
        for (TreeNode<T> node : flatList) {
            T parentId = node.getParentId();
            if (parentId == null || parentId.equals(rootParentId)) {
                // 根节点
                treeList.add(node);
            } else {
                // 非根节点,查找父节点
                TreeNode<T> parent = nodeMap.get(parentId);
                if (parent != null) {
                    parent.getChildren().add(node);
                }
            }
        }
        return treeList;
    }
}

递归构建(适合小数据集)

public class RecursiveTreeBuilder {
    public static <T> List<TreeNode<T>> buildTree(List<TreeNode<T>> flatList, T parentId) {
        List<TreeNode<T>> treeNodes = new ArrayList<>();
        for (TreeNode<T> node : flatList) {
            if (parentId == null && node.getParentId() == null ||
                parentId != null && parentId.equals(node.getParentId())) {
                // 递归查找子节点
                node.setChildren(buildTree(flatList, node.getId()));
                treeNodes.add(node);
            }
        }
        return treeNodes;
    }
}

树形数据的显示规整

1 控制台输出(带缩进)

public class TreePrinter {
    public static <T> void printTree(List<TreeNode<T>> treeList) {
        for (TreeNode<T> node : treeList) {
            printNode(node, 0);
        }
    }
    private static <T> void printNode(TreeNode<T> node, int depth) {
        // 缩进
        StringBuilder indent = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            indent.append("  ");
        }
        // 打印节点信息
        System.out.println(indent + "├─ " + node.getName());
        // 递归打印子节点
        if (node.getChildren() != null) {
            List<TreeNode<T>> children = node.getChildren();
            for (int i = 0; i < children.size(); i++) {
                TreeNode<T> child = children.get(i);
                printNode(child, depth + 1);
            }
        }
    }
}

2 JSON输出(用于前端展示)

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public class TreeJsonFormatter {
    public static <T> String toJson(List<TreeNode<T>> treeList) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        return mapper.writeValueAsString(treeList);
    }
    // 自定义格式化,添加层级和路径信息
    public static <T> List<Map<String, Object>> formatForView(List<TreeNode<T>> treeList) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (TreeNode<T> node : treeList) {
            result.add(formatNode(node, 1, "0"));
        }
        return result;
    }
    private static <T> Map<String, Object> formatNode(TreeNode<T> node, int level, String path) {
        Map<String, Object> nodeMap = new LinkedHashMap<>();
        nodeMap.put("id", node.getId());
        nodeMap.put("name", node.getName());
        nodeMap.put("level", level);
        nodeMap.put("path", path + "-" + node.getId());
        nodeMap.put("isLeaf", node.getChildren() == null || node.getChildren().isEmpty());
        // 递归处理子节点
        if (node.getChildren() != null && !node.getChildren().isEmpty()) {
            List<Map<String, Object>> childrenList = new ArrayList<>();
            nodeMap.put("children", childrenList);
            for (TreeNode<T> child : node.getChildren()) {
                childrenList.add(formatNode(child, level + 1, path + "-" + node.getId()));
            }
        }
        return nodeMap;
    }
}

完整案例:部门树

实体类

public class Department {
    private Long id;
    private Long parentId;
    private String name;
    private String description;
    // 转换为树节点
    public TreeNode<Long> toTreeNode() {
        TreeNode<Long> node = new TreeNode<>();
        node.setId(this.id);
        node.setParentId(this.parentId);
        node.setName(this.name);
        // 可以添加额外信息
        node.setExtData(this);
        return node;
    }
}

使用示例

public class TreeDemo {
    public static void main(String[] args) {
        // 1. 模拟数据库查询结果
        List<Department> departments = getDepartmentsFromDB();
        // 2. 转换为树节点列表
        List<TreeNode<Long>> nodeList = departments.stream()
            .map(Department::toTreeNode)
            .collect(Collectors.toList());
        // 3. 构建树
        List<TreeNode<Long>> tree = TreeBuilder.buildTree(nodeList, null);
        // 4. 规整输出
        System.out.println("=== 树形结构(控制台)===");
        TreePrinter.printTree(tree);
        System.out.println("\n=== JSON输出 ===");
        try {
            String json = TreeJsonFormatter.toJson(tree);
            System.out.println(json);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("\n=== 前端友好格式 ===");
        List<Map<String, Object>> viewData = TreeJsonFormatter.formatForView(tree);
        viewData.forEach(System.out::println);
    }
}

常用工具类库推荐

场景 特点
Apache Commons Collections 集合操作 提供 CollectionUtils 等工具
Jackson JSON 序列化 JsonNode 可以天然表示树形
Lombok 简化模型 @Data 自动生成 getter/setter
MyBatis-Plus 数据库查询 TreeSelect 注解支持递归查询
Hutool 通用工具 TreeUtil 提供树构建和遍历

性能优化建议

  1. 数据库层面

    • 使用 WITH RECURSIVE(MySQL 8+)直接查询树结构
    • 添加 level、path 字段存储层级信息
  2. Java处理优化

    • 使用 HashMap 存储节点(O(1)查找)
    • 避免递归过深(设置最大深度)
    • 使用并行流处理大型数据集
  3. 展示优化

    • lazy load(延迟加载子节点)
    • 只加载当前层级的数据
    • 前端使用虚拟滚动

规整Java树形结构的关键在于:

  1. 通用数据模型 - 支持任意类型的主键
  2. 高效构建算法 - 推荐两次遍历法
  3. 灵活的展示格式 - 支持控制台、JSON、前端等多种输出
  4. 合理的性能优化 - 根据数据量选择合适的方案

根据实际业务场景(数据量大小、展示要求、性能需求)选择最适合的方案即可。

抱歉,评论功能暂时关闭!