开发者

构建Java树结构的三种实现方法

目录
  • 一、准备工作
    • 表结构
    • 部分表数据
  • 二、三种方式
    • controller层
    • 构建树结构工具类(三种方式)
    • 执行结javascript
  • 总结

    一、准备工作

    表结构

    CREATE TABLE `asset_classification` (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
      `className` varchar(50) NOT NULL COMMENT '分类名',
      `status` tinyint(2) NOT NULL COMMENT '状态(0:使用中 1:停用)',
      `type` tinyint(2) NOT NULL COMMENT '类别(0:设备 1:物料 2:附件)',
      `writeable` tinyint(2) NOT NULL COMMENT '1:不可编辑 0:可编辑',
      `parentId` int(11) NOT NULL COMMENT '父类id',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=157 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT;

    部分表数据

    构建Java树结构的三种实现方法

    二、三种方式

    • 原始递归
    • 利用Java 8 Stream流进行处理(原理还是递归)
    • Stream流升级构建

    controller层

    @RestController
    public class TestController {
    
        @Autowired
        private AssetClassificationBiz assetClassificationBiz;
    
        @GetMapping("/tree")
        public HttpResponseTemp<?> getTree(){
    
            List<AssetClassification> assetClassificationList = assetClassificationBiz.selectAll();
    
            List<TreeUtil.TreeSelect> list = new ArrayList<>();
    
            for (AssetClassification assetClassification : assetClassificationList) {
                TreeUtil.TreeSelect treeSelect = new TreeUtil.TreeSelect();
                treeSelect.setId(Convert.toLong(assetClassification.getId()));
                treeSelect.setLabel(assetClassification.getClassName());
                treeSelect.setParentId(Convert.toLong(assetClassification.getParentId()));
                list.add(treeSelect);
            }
    
            //原始递归
            List<TreeUtil.TreeSelect> list1 = TreeUtil.buildTree(list);
            //利用Java 8 Stream流进行处理(原理还是递归)
            List<TreeUtil.TreeSelect> list2 = TreeUtil.buildTreeByStream(list);
            //Stream流升级构建
            List<TreeUtil.TreeSelect> list3 = TreeUtil.buildTreeByAllStream(list);
    
            return ResultStat.OK.wrap(list3);
        }
    }

    构建树结构工具类(三种方式)

    /**
     * @ClassName TreeUtil
     * @Description 构建树结构工具类
     * @Author hl
     * @Date 2022/9/28 15:13
     * @Version 1.0
     */
    public class TreeUtil {
    
    
        /**
         * Stream流升级构建
         * @param trees
         * @return
         */
        public static List<TreeSelect> buildTreeByAllStream(List<TreeSelect> trees){
            return trees.stream().filter(m -> m.getParentId() == 0).peek(
                    (m) -> m.setChildren(getChildrenList(m, trees))
         kxtjl   ).collect(Collectors.toList());
    
        }
    
        /**
         * 获取子节点列表
         * @param tree
         * @param list
         * @return
         */
        public static List<TreeSelect> getChildrenList(TreeSelect tree, List<TreeSelect> list){
            return list.stream().filter(item -> Objects.equals(item.getParentId(), tree.getId())).peek(
                    (item) -> item.setChildren(getChildrenList(item, list))
     编程       ).collect(Collectors.toList());
        }
    
    
    
        /**
         * 利用Java 8 Stream流进行处理(原理还是递归)
         * @param trees
         * @return
         */
        public static List<TreeSelect> buildTreeByStream(List<TreeSelect> trees){
            //获取parentId = 0的根节点
            List<TreeSelect> list = trees.stream().filter(item -> item.getParentId() == 0L).collect(Collectors.toList());
            //根据parentId进行分组
            Map<Long, List<TreeSelect>> map = trees.stream().collect(Collectors.groupingBy(TreeSelect::getParentId));
            recursionFnTree(list, map);
            return list;
        }
    
        /**
         * 递归遍历节点
         * @param list
         * @param map
         */
        public static void recursionFnTree(List<TreeSelect> list, Map<Long, List<TreeSelect>> map){
            for (TreeSelect treeSelect : list) {
                List<TreeSelect> childList = map.get(treeSelect.getId());
                treeSelect.setChildren(childList);
                if (null != childList && 0 < childList.size()){
                    recursionFnTree(childList,map);
                }
            }
        }
    
    
        /**
         * 构建前端所需要树结构
         *
         * @param trees 列表
         * @return 树结构列表
         */
        public static List<TreeSelect> buildTree(List<TreeSelect> trees) {
            List<TreeSelect> returnList = new ArrayList<>();
            List<Long> tempList = new ArrayList<>();
            for (TreeSelect tree : trees) {
                tempList.add(tree.getId());
            }
    
            for (TreeSelect treeSelect : trees) {
                // 如果是顶级节点, 遍历该父节点的所有子节点
                if (!tempList.contains(treeSelect.getParentId())) {
                    recursionFn(trees, treeSelect);
                    returnList.add(treeSelect);
                }
            }
    
            if (returnList.isEmpty()) {
                returnList = trees;
            }
            return returnList;
        }
        /**
         * 递归列表
         */
        private static void recursionFn(List<TreeSelect> list, TreeSelect t) {
            // 得到子节点列表
            List<TreeSelect> childList = getChildList(list, t);
            t.setChildren(childList);
            for (TreeSelect tChild : childList) {
                if (hasChild(list, tChild)) {
                    recursionFn(list, tChild);
                }
            }
        }
    
        /**
         * 得到子节点列表
         */
        private static List<TreeSelect> getChildList(List<TreeSelect> list, TreeSelect t) {
            List<TreeSelect> tlist = new ArrayList<>();
            for (TreeSelect n : list) {
                if (ObjectUtil.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) {
                    tlist.add(n);
                }
            }
            return tlist;
        }
    
        /**
         * 判断是否有子节点
         */
        private static boolean hasChild(List<TreeSelect> list, TreeSelect t) {
            return getChildList(list, t).size() > 0;
        }
    
    
    
        static class TreeSelect implements Serializable {
    
            /** 节点ID */
            private Long id;
    
     js       /** 节点名称 */
            private String label;
    
            /** 父ID */
            private Long http://www.devze.comparentId;
    
            /** 子节点 */
            private List<TreeSelect> children;
    
            public Long getId() {
                return id;
            }
    
            public void setId(Long id) {
                this.id = id;
            }
    
            public String getLabel() {
                return label;
            }
    
            public void setLabel(String label) {
                this.label = label;
            }
    
            public List<TreeSelect> getChildren() {
                return children;
            }
    
            public void setChildren(List<TreeSelect> children) {
                this.children = children;
            }
    
            public Long getParentId() {
                return parentId;
            }
    
            public void setParentId(Long parentId) {
                this.parentId = parentId;
            }
        }
    }

    执行结果

    构建Java树结构的三种实现方法

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜