树结构递归构建总结

1、常规表结构设计

tree_meta_data

字段名

描述

备注

id

主键Id

 

name

名称

 

parent_id

父Id

 

path

路径等

 

id_path

id路径

可以通过id_path快速查找

2、构建树结构

2.1 思想

  1. 从数据库表tree_meta_data获取元数据;
  2. 根据parentId=0,遍历找到所有父节点;
  3. 遍历找到的父节点,递归找到每个父节点的所有子节点;

2.2 对象类

(1)元数据

/**
 * 树元数据(表中数据)
 *
 * @author xingnana
 * @create 12/14/20
 */
@Data
@AllArgsConstructor
public class TreeMetaData {
    private Long id;

    private String name;

    private Long parentId;

    private String path;

    private String idPath;
}

(2)定义node对象

/**
 * 树节点
 *
 * @author xingnana
 * @create 12/14/20
 */
@Data
@NoArgsConstructor
public class TreeNode {
    private Long id;
    private String name;
    private List<TreeNode> children = new ArrayList<>(); //子模块列表

    /**
     * 是否勾选
     */
    private Boolean isCheck;

    /**
     * 模块路径
     */
    private String path;

    public TreeNode(Long id, String name) {
        this.id = id;
        this.name = name;
        this.isCheck = false;
    }
}

2.3 构建完整树主要逻辑

/**
     * 构建树
     */
    private List<TreeNode> buildTree(List<TreeMetaData> dataList) {
        List<TreeNode> treeNodeList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(dataList)) {
            Iterator<TreeMetaData> iterator = dataList.iterator();

            /** 找到所有父节点*/
            while (iterator.hasNext()) {
                TreeMetaData eachDO = iterator.next();
                if (eachDO.getParentId() == 0) { //找到父节点
                    TreeNode parentNode = new TreeNode(eachDO.getId(), eachDO.getName());
                    parentNode.setPath(eachDO.getPath());
                    treeNodeList.add(parentNode);
                    iterator.remove();
                }
            }

            //找所有父节点的子节点
            if (!treeNodeList.isEmpty()) {
                for (TreeNode parent : treeNodeList) {
                    findChildren(parent, dataList);
                }
            }
        }
        return treeNodeList;
    }

    /**
     * 找到父节点的所有子节点
     *
     * @param parent
     * @param doList
     */
    private void findChildren(TreeNode parent, List<TreeMetaData> doList) {
        Iterator<TreeMetaData> iterator = doList.iterator();
        while (iterator.hasNext()) {
            TreeMetaData eachDO = iterator.next();
            if (Objects.equals(parent.getId(), eachDO.getParentId())) {
                TreeNode nodeVO = new TreeNode(eachDO.getId(), eachDO.getName());
                nodeVO.setPath(eachDO.getPath());
                parent.getChildren().add(nodeVO);
                iterator.remove();
            }
        }

        for (TreeNode child : parent.getChildren()) {
            findChildren(child, doList);
        }

    }

 

2.4 根据选中节点,构建选中节点树

/**
     * 根据选中的树结点构造树
     */
    private List<TreeNode> buildCheckedTree(List<TreeMetaData> dataList, List<Long> checkedIds) {
        List<TreeNode> treeNodeList = new ArrayList<>();
        if (dataList != null) {
            Iterator<TreeMetaData> iterator = dataList.iterator();
            /** 找到所有父节点*/
            while (iterator.hasNext()) {
                TreeMetaData eachDO = iterator.next();
                /** 父节点parentId=0*/
                if (eachDO.getParentId() == 0) {
                    TreeNode parentNode = new TreeNode(eachDO.getId(), eachDO.getName());
                    parentNode.setIsCheck(false);
                    parentNode.setPath(eachDO.getPath());
                    treeNodeList.add(parentNode);
                    iterator.remove();
                }
            }

            /** 找到父节点的所有子节点*/
            if (!treeNodeList.isEmpty()) {
                for (TreeNode parent : treeNodeList) {
                    findCheckedChildren(parent, dataList, checkedIds);
                }
            }

            /** 找到父节点的所有子节点*/
            if (!treeNodeList.isEmpty()) {
                for (TreeNode parent : treeNodeList) {
                    findCheckedChildren(parent, dataList, checkedIds);
                }
            }
        }

        return treeNodeList;
    }

    /**
     * 根据选中的树结点查找子节点
     *
     * @param parent 父节点
     * @param dataList
     * @param checkedIds 选中节点的id
     */
    private void findCheckedChildren(TreeNode parent, List<TreeMetaData> dataList, List<Long> checkedIds) {
        Iterator<TreeMetaData> iterator = dataList.iterator();
        while (iterator.hasNext()) {
            TreeMetaData eachDO = iterator.next();
            /** 循环 找子节点*/
            if (Objects.equals(parent.getId(), eachDO.getParentId())) {
                TreeNode nodeVO = new TreeNode(eachDO.getId(), eachDO.getName());
                nodeVO.setIsCheck(checkedIds.contains(nodeVO.getId()) ? true : false);
                nodeVO.setPath(eachDO.getPath());
                parent.getChildren().add(nodeVO);
                iterator.remove();
            }
        }

        boolean isAllCheck = true;

        /** 找到父节点的所有子节点 且 若子节点全部选中,则选中父节点 */
        for (TreeNode child : parent.getChildren()) {
            findCheckedChildren(child, dataList, checkedIds);
            if (!child.getIsCheck()) {
                isAllCheck = false;
            }
        }

        if (!CollectionUtils.isEmpty(parent.getChildren())) {
            parent.setIsCheck(isAllCheck);
        } else if (checkedIds.contains(parent.getId())) {
            parent.setIsCheck(true);
        }

    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值