• TreeUtils工具类一行代码实现列表转树【第三版优化】 三级菜单 三级分类 附视频


    一、序言

    在日常一线开发过程中,总有列表转树的需求,几乎是项目的标配,比方说做多级菜单、多级目录、多级分类等,有没有一种通用且跨项目的解决方式呢?帮助广大技术朋友给业务瘦身,提高开发效率。

    本文将基于Java8的Lambda 表达式和Stream等知识,使用TreeUtils工具类实现一行代码完成列表转树这一通用型需求。本文有配套视频,传送门直达。

    需要说明的是,本TreeUtils工具类已进行三版优化,能够胜任生产场景绝大多数列表转树的。

    二、实战编码

    1、引入坐标

    本坐标地址包含TreeUtils工具类方法,已经发布到Maven中央仓库,建议使用最新的版本号,本文发布时版本是1.5.8.3,若有最新版本,建议使用最新版本。

    学习源码的朋友,源码直通车

    <dependency>
        <groupId>xin.altitude.cmsgroupId>
        <artifactId>ucode-cms-commonartifactId>
        <version>1.5.8.3version>
    dependency>
    
    2、编写DO

    DO是访问数据库实体类,属于前期准备素材。

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @TableName(value = "bu_category3")
    public class Category {
        private static final long serialVersionUID = 1L;
        @TableId(type = IdType.AUTO)
        private String id;
        private String name;
        private String parentId;
        private String remark;
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime createTime;
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime updateTime;
        
        public Category(Category category) {
            if (Objects.nonNull(category)) {
                this.id = category.id;
                this.name = category.name;
                this.parentId = category.parentId;
                this.remark = category.remark;
                this.createTime = category.createTime;
                this.updateTime = category.updateTime;
            }
        }
    }
    
    3、创建BO

    创建BO数据模型用于构造属性结点

    @Data
    @NoArgsConstructor
    public class CategoryBo {
        private String id;
        private String name;
        private String parentId;
        private String remark;
        /**
         * 孩子结点 名字任意取
         */
        private List childList;
        /**
         * 实现Category 转 CategoryBo
         *
         * @param category
         */
        public CategoryBo(Category category) {
            if (Objects.nonNull(category)) {
                this.id = category.getId();
                this.name = category.getName();
                this.parentId = category.getParentId();
                this.remark = category.getRemark();
            }
        }
    }
    
    3、调用TreeUtils工具类

    在服务层调用TreeUtils工具类,一行代码完成转换。

    /**
     * 获取DO中指定的属性 并构造成树
     * @return
     */
    public List selectCategory4() {
        List categoryList = this.list();
        List categoryBoList = EntityUtils.toList(categoryList, CategoryBo::new);
        return TreeUtils.createNodeDetail(categoryBoList, "000000", CategoryBo::getId, CategoryBo::getParentId, CategoryBo::getChildList);
    }
    
    4、效果展示

    原始列表数据

    {
      "code": 200,
      "msg": "操作成功",
      "data": [
        {
          "id": "310000",
          "name": "电子商务",
          "parentId": "000000",
          "remark": "EEEEE",
          "createTime": null,
          "updateTime": "2021-11-21 11:22:40"
        },
        {
          "id": "310100",
          "name": "大宗商品",
          "parentId": "310000",
          "remark": "JJJJJ",
          "createTime": null,
          "updateTime": "2021-11-21 11:22:52"
        },
        {
          "id": "310101",
          "name": "大宗商品综合",
          "parentId": "310100",
          "remark": "IIIII",
          "createTime": null,
          "updateTime": "2021-11-21 11:22:58"
        },
        {
          "id": "310102",
          "name": "钢铁类电商",
          "parentId": "310100",
          "remark": "OOOOO",
          "createTime": null,
          "updateTime": "2021-11-21 11:23:02"
        },
        {
          "id": "310200",
          "name": "综合电商",
          "parentId": "310000",
          "remark": "NNNNN",
          "createTime": null,
          "updateTime": "2021-11-21 11:23:07"
        }
      ]
    }
    

    树状层次数据

    {
      "code": 200,
      "msg": "操作成功",
      "data": [
        {
          "id": "310000",
          "name": "电子商务",
          "parentId": "000000",
          "remark": "EEEEE",
          "childList": [
            {
              "id": "310100",
              "name": "大宗商品",
              "parentId": "310000",
              "remark": "JJJJJ",
              "childList": [
                {
                  "id": "310101",
                  "name": "大宗商品综合",
                  "parentId": "310100",
                  "remark": "IIIII",
                  "childList": []
                },
                {
                  "id": "310102",
                  "name": "钢铁类电商",
                  "parentId": "310100",
                  "remark": "OOOOO",
                  "childList": []
                }
              ]
            },
            {
              "id": "310200",
              "name": "综合电商",
              "parentId": "310000",
              "remark": "NNNNN",
              "childList": []
            }
          ]
        }
      ]
    }
    

    三、小结

    通过一个小小的高频业务场景,抽离业务共性,屏蔽业务细节,实现了通用型业务逻辑的编码。

    希望广大技术朋友在完成日常开发工作的前提下,能够进一步打磨代码,感受编程之美。

  • 相关阅读:
    程序员大厂之鹅厂探秘
    1-10、信息 / 个人信息 / 数字化 / 数字经济 / 生产要素 / 数据要素 / 数据 / 公共数据 / 企业数据 / 个人数据
    数据分析 | Pandas 200道练习题,每日10道题,学完必成大神(5)
    C++11右值引用的价值体现
    Maven知识【IDEA使用Maven&依赖管理】第三章
    手把手教学:二阶魔方还原
    nginx浏览器缓存和上流缓存expires指令_nginx配置HTTPS
    流媒体分析之rtmp 协议flv 封装
    leetcode 121. 买卖股票的最佳时机、122. 买卖股票的最佳时机 II
    PKI/TLS 工具之CFSSL —— 筑梦之路
  • 原文地址:https://www.cnblogs.com/javazhishitupu/p/16914381.html