Java树状结构数据构建(基于hutool)

简介: Java树状结构数据构建(基于hutool)

一、应用场景

权限菜单

商品分类

需要返回类似数据结构

{
  "data": [
    {
      "id": 1,
      "parentId": 0,
      "name": "根节点",
      "children": [
        {
          "id": 2,
          "parentId": 1,
          "name": "王二"
        },
        {
          "id": 3,
          "parentId": 1,
          "name": "王1二"
        }
      ]
    },
    {
      "id": 4,
      "parentId": 0,
      "name": "一级目"
    },
    {
      "id": 5,
      "parentId": 0,
      "name": "一级目2",
      "children": [
        {
          "id": 6,
          "parentId": 5,
          "name": "一级目2"
        }
      ]
    }
  ]
}

二、推荐工具

使用hutool工具的树结构工具-TreeUtil

电梯:Hutool参考文档

导入依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.22</version>
</dependency>

三、数据准备

层级数据表一般会涉及三个必填字段:数据->id,父级ID->pid,数据排序->sort;

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for system_classification
-- ----------------------------
DROP TABLE IF EXISTS `system_classification`;
CREATE TABLE `system_classification`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
  `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '分类名称',
  `parent_id` bigint(20) NULL DEFAULT 0 COMMENT '父分类id',
  `sort` int(11) NOT NULL DEFAULT 0 COMMENT '显示顺序',
  `level` int(11) NULL DEFAULT NULL COMMENT '层级',
  `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '分类状态(0正常 1停用)',
  `deth` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '纵深',
  `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
  `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间',
  `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
  `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  `tenant_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '租户编号',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '部门表' ROW_FORMAT = Dynamic;
 
-- ----------------------------
-- Records of system_classification
-- ----------------------------
INSERT INTO `system_classification` VALUES (1, '根节点', 0, 0, 1, 0, '1', 'admin', '2021-01-05 17:03:47', '1', '2022-03-22 10:18:56', b'0', 1);
INSERT INTO `system_classification` VALUES (2, '王二', 1, 1024, 2, 0, '1', '1', '2022-03-18 11:35:43', '1', '2022-03-22 10:19:00', b'0', 1);
INSERT INTO `system_classification` VALUES (3, '王1二', 1, 1024, 2, 0, '1', '1', '2022-03-18 11:38:05', '1', '2022-03-22 10:19:02', b'0', 1);
INSERT INTO `system_classification` VALUES (4, '一级目', 0, 1, 1, 0, NULL, '1', '2022-03-22 10:09:25', '1', '2022-03-22 10:09:25', b'0', 1);
INSERT INTO `system_classification` VALUES (5, '一级目2', 0, 1, 1, 0, NULL, '1', '2022-03-22 10:09:32', '1', '2022-03-22 10:09:32', b'0', 1);
INSERT INTO `system_classification` VALUES (6, '二级目2', 5, 1, 2, 0, '5', '1', '2022-03-22 10:09:40', '1', '2022-03-22 10:14:17', b'0', 1);
INSERT INTO `system_classification` VALUES (7, 'san级目2', 6, 1, 3, 0, '5,6', '1', '2022-03-22 10:19:28', '1', '2022-03-22 10:19:28', b'0', 1);
 
SET FOREIGN_KEY_CHECKS = 1;

数据对应实体类

public class ClassificationDO {
 
    /**
     * 分级ID
     */
    @TableId
    private Long id;
    /**
     * 分级名称
     */
    private String name;
    /**
     * 父分级ID
     *
     * 关联 {@link #id}
     */
    private Long parentId;
    /**
     * 显示顺序
     */
    private Integer sort;
 
    /**
     * 层级
     */
    private Integer level;
    /**
     * 纵深
     *
     */
    private String deth;
 
    /**
     * 分级状态
     *
     * 枚举 {@link CommonStatusEnum}
     */
    private Integer status;
    /**
     * 多租户编号
     */
    private Long tenantId;
 
}
 
 

四、实现细节

根据pid与id的逻辑关系构建tree;

public CommonResult<List<Tree<Integer>>> listClassificationsChildren() {
        //返回的业务数据
        List<ClassificationDO> list = classificationService.getSimpleClassifications();
        log.info(JSON.toJSONString(list));
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的
         //数据ID
        treeNodeConfig.setIdKey("id");
        // 父级id字段
        treeNodeConfig.setParentIdKey("parentId");
        // 排序字段,这个字段不能是null,不然会报错,默认最好是数字
        treeNodeConfig.setWeightKey("sort");       
        // 最大递归深度
        //treeNodeConfig.setDeep(3);
        //转换器
        List<Tree<Integer>> build = TreeUtil.build(list, 0, treeNodeConfig, ((object, treeNode) -> {
            treeNode.setId(object.getId().intValue());//id
            treeNode.setParentId(object.getParentId().intValue());//父id
            treeNode.putExtra("name", object.getName());
            treeNode.putExtra("sort", object.getSort());
            treeNode.putExtra("level", object.getLevel());
            treeNode.putExtra("status", object.getStatus());
        }));
        log.info(JSON.toJSONString(build));
        return success(build);
    }

查询返回的数据

 [{"createTime":1647574543000,"creator":"1","deleted":false,"deth":"1","id":2,"level":2,"name":"王二","parentId":1,"sort":1024,"status":0,"tenantId":1,"updateTime":1647915540000,"updater":"1"},{"createTime":1647917632000,"creator":"1","deleted":false,"id":8,"level":1,"name":"测试1","parentId":0,"sort":5,"status":0,"tenantId":1,"updateTime":1647917638000,"updater":"1"},{"createTime":1647917993000,"creator":"1","deleted":false,"deth":"1,1","id":10,"level":2,"name":"张三","parentId":1,"sort":2,"status":0,"tenantId":1,"updateTime":1647917993000,"updater":"1"},{"createTime":1647918003000,"creator":"1","deleted":false,"deth":"1,1,10","id":11,"level":3,"name":"张小三","parentId":10,"sort":1,"status":0,"tenantId":1,"updateTime":1647918003000,"updater":"1"},{"createTime":1647917776000,"creator":"1","deleted":false,"id":9,"level":1,"name":"小王","parentId":0,"sort":1,"status":0,"tenantId":1,"updateTime":1647917776000,"updater":"1"},{"createTime":1647915568000,"creator":"1","deleted":false,"deth":"5,6","id":7,"level":3,"name":"san级目2","parentId":6,"sort":1,"status":0,"tenantId":1,"updateTime":1647915568000,"updater":"1"},{"createTime":1647914980000,"creator":"1","deleted":false,"deth":"5","id":6,"level":2,"name":"二级目2","parentId":5,"sort":1,"status":0,"tenantId":1,"updateTime":1647915257000,"updater":"1"},{"createTime":1647914972000,"creator":"1","deleted":false,"id":5,"level":1,"name":"一级目2","parentId":0,"sort":1,"status":0,"tenantId":1,"updateTime":1647914972000,"updater":"1"},{"createTime":1647914965000,"creator":"1","deleted":false,"id":4,"level":1,"name":"一级目","parentId":0,"sort":1,"status":0,"tenantId":1,"updateTime":1647914965000,"updater":"1"},{"createTime":1609837427000,"creator":"admin","deleted":false,"deth":"1","id":1,"level":1,"name":"根节点","parentId":0,"sort":0,"status":0,"tenantId":1,"updateTime":1647915536000,"updater":"1"}]

排序后的数据

 [{"id":1,"parentId":0,"name":"根节点","sort":0,"level":1,"status":0,"children":[{"id":10,"parentId":1,"name":"张三","sort":2,"level":2,"status":0,"children":[{"id":11,"parentId":10,"name":"张小三","sort":1,"level":3,"status":0}]},{"id":2,"parentId":1,"name":"王二","sort":1024,"level":2,"status":0}]},{"id":9,"parentId":0,"name":"小王","sort":1,"level":1,"status":0},{"id":5,"parentId":0,"name":"一级目2","sort":1,"level":1,"status":0,"children":[{"id":6,"parentId":5,"name":"二级目2","sort":1,"level":2,"status":0,"children":[{"id":7,"parentId":6,"name":"san级目2","sort":1,"level":3,"status":0}]}]},{"id":4,"parentId":0,"name":"一级目","sort":1,"level":1,"status":0},{"id":8,"parentId":0,"name":"测试1","sort":5,"level":1,"status":0}]

接口返回的数据

{
  "code": 0,
  "data": [
    {
      "id": 1,
      "parentId": 0,
      "name": "根节点",
      "sort": 0,
      "level": 1,
      "status": 0,
      "children": [
        {
          "id": 10,
          "parentId": 1,
          "name": "张三",
          "sort": 2,
          "level": 2,
          "status": 0,
          "children": [
            {
              "id": 11,
              "parentId": 10,
              "name": "张小三",
              "sort": 1,
              "level": 3,
              "status": 0
            }
          ]
        },
        {
          "id": 2,
          "parentId": 1,
          "name": "王二",
          "sort": 1024,
          "level": 2,
          "status": 0
        }
      ]
    },
    {
      "id": 9,
      "parentId": 0,
      "name": "小王",
      "sort": 1,
      "level": 1,
      "status": 0
    },
    {
      "id": 5,
      "parentId": 0,
      "name": "一级目2",
      "sort": 1,
      "level": 1,
      "status": 0,
      "children": [
        {
          "id": 6,
          "parentId": 5,
          "name": "二级目2",
          "sort": 1,
          "level": 2,
          "status": 0,
          "children": [
            {
              "id": 7,
              "parentId": 6,
              "name": "san级目2",
              "sort": 1,
              "level": 3,
              "status": 0
            }
          ]
        }
      ]
    },
    {
      "id": 4,
      "parentId": 0,
      "name": "一级目",
      "sort": 1,
      "level": 1,
      "status": 0
    },
    {
      "id": 8,
      "parentId": 0,
      "name": "测试1",
      "sort": 5,
      "level": 1,
      "status": 0
    }
  ],
  "msg": ""
}
目录
相关文章
|
2天前
|
Java
使用kafka-clients操作数据(java)
使用kafka-clients操作数据(java)
13 6
|
2天前
|
算法 搜索推荐 Java
Java插入排序:优雅整理数据的艺术
Java插入排序:优雅整理数据的艺术
|
2天前
|
Java 关系型数据库 开发者
Java编程设计原则:构建稳健、可维护的软件基石
Java编程设计原则:构建稳健、可维护的软件基石
|
2天前
|
存储 安全 Java
深入理解Java内存模型(JMM)与虚拟机的内存结构(JVM)
深入理解Java内存模型(JMM)与虚拟机的内存结构(JVM)
|
2天前
|
XML Java 定位技术
详尽分享经纬坐标(BLH)数据创建.kml文件小工具设计Java版
详尽分享经纬坐标(BLH)数据创建.kml文件小工具设计Java版
|
2天前
|
消息中间件 监控 Java
使用Java构建微服务架构的最佳实践
使用Java构建微服务架构的最佳实践
|
2天前
|
监控 Java 持续交付
构建Java微服务架构的CI/CD流程
构建Java微服务架构的CI/CD流程
|
2天前
|
缓存 监控 算法
构建高性能Java应用的秘诀
构建高性能Java应用的秘诀
|
2天前
|
Java 开发者
构建健壮的Java应用:错误处理与日志管理
构建健壮的Java应用:错误处理与日志管理
|
3天前
|
JSON JavaScript Java
如何在Java中处理JSON数据?
如何在Java中处理JSON数据?