常见的树形封装工具类

实体类

@Data
public class TreeData {
    private static final long serialVersionUID = 1L;

    /** 节点ID */
    @Schema(description = "节点ID", example = "1")
    private String id;

    /** 父节点ID:顶级节点为0 */
    @Schema(description = "父节点ID", example = "1")
    private String parentId;

    /** 节点名称 */
    @Schema(description = "节点名称", example = "1")
    private String name;


    @Schema(description = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    @Schema(description = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;

    /** 子节点 */
    private List<TreeData> children;

    
    public TreeData() {

    }
    //通过指定构造器函数可以快速的完成实体类转换


}

工具类

public class TreeUtils {


//-------------------以下是固定类转换树形结构------------------------------------

    /**
    * @Author: zhangsk
    * @Description:   修改形成树工具类方法 ----同一改为使用改方法
    * @DateTime: 14:24 2024/3/21
    * @Params:
    * @Return
    */
    public static List<TreeData> buildDeptTree(Set<TreeData> depts) {
        List<TreeData> returnList = new ArrayList<TreeData>();
        List<String> tempList = new ArrayList<>();
        for (TreeData dept : depts) {
            tempList.add(dept.getId());
        }
        for (Iterator<TreeData> iterator = depts.iterator(); iterator.hasNext(); ) {
            TreeData dept = (TreeData) iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = depts.stream().collect(Collectors.toList());
        }
        return returnList;
    }



    /**
     * 得到子节点列表
     */
    private static List<TreeData> getChildList(Set<TreeData> list, TreeData t) {
        List<TreeData> tlist = new ArrayList<TreeData>();
        Iterator<TreeData> it = list.iterator();
        while (it.hasNext()) {
            TreeData n = (TreeData) it.next();
            if (StringUtils.isNotEmpty(n.getParentId()) && n.getParentId().equals(t.getId())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 递归列表
     */
    private static void recursionFn(Set<TreeData> list, TreeData t) {
        // 得到子节点列表
        List<TreeData> childList = getChildList(list, t);
        t.setChildren(childList);
        for (TreeData tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            } else {
                // 没有子节点,设置children为空
                tChild.setChildren(new ArrayList<>());
            }
        }
    }

    /**
     * 判断是否有子节点
     */
    private static boolean hasChild(Set<TreeData> list, TreeData t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }
//------------------------------------------------------------------

    // 部门顶级父级id
    private  static String PARENT_ID = "1";

    // 保存参与构建树形的所有数据(通常数据库查询结果)
    public Set<TreeData> nodeList = new HashSet<>();

    /**
     *  构造方法
     *  @param nodeList 将数据集合赋值给nodeList,即所有数据作为所有节点。
     */
    public TreeUtils(Set<TreeData> nodeList){
        this.nodeList = nodeList;
    }

    /**
     * 对部门集合数据进行转换
     * @param deptList
     * @return
     */
    public static Set<TreeData> exchangeToTree(List<DeptRespDTO> deptList){
        if (CollectionUtils.isEmpty(deptList)) {
            return null;
        }
        //集合数据进行对象转换
        Set<TreeData> list = new HashSet<>();
        for (DeptRespDTO fileDeptDO : deptList) {
            TreeData tree = new TreeData(String.valueOf(fileDeptDO.getId()), String.valueOf(fileDeptDO.getParentId()), fileDeptDO.getName());
            list.add(tree);
        }
        return list;
    }


    public static Set<TreeData> exchangeToTree01(List<DeptTreeRespDTO> deptList){
        if (CollectionUtils.isEmpty(deptList)) {
            return null;
        }
        //集合数据进行对象转换
        Set<TreeData> list = new HashSet<>();
        for (DeptTreeRespDTO fileDeptDO : deptList) {
            TreeData tree = new TreeData(String.valueOf(fileDeptDO.getId()), String.valueOf(fileDeptDO.getParentId()), fileDeptDO.getName());
            list.add(tree);
        }
        return list;
    }


    /**
     *  根据每一个顶级节点(根节点)进行构建树形结构
     *  @return  构建整棵树
     */
    public List<TreeData> buildTree(String id){
        // treeNodes:保存一个顶级节点所构建出来的完整树形
        List<TreeData> treeNodes = new ArrayList<TreeData>();
        // getRootNode():获取所有的根节点
        for (TreeData treeRootNode : getRootNode(id)) {
            // 将顶级节点进行构建子树
            treeRootNode = buildChildTree(treeRootNode);
            // 完成一个顶级节点所构建的树形,增加进来
            treeNodes.add(treeRootNode);
        }
        return treeNodes;
    }

    /**
     *   获取需构建的所有根节点(顶级节点) "1"
     *   @return 所有根节点List集合
     */
    public List<TreeData> getRootNode(String id) {
        if (CollectionUtils.isEmpty(nodeList)) {
            return null;
        }
        String pid = null;
        if (id != null) {
             pid = id;
        } else {
            pid = PARENT_ID;
        }
        List<TreeData> rootlist = new ArrayList<>();
        for (TreeData treeData : nodeList) {
            if (treeData != null && treeData.getParentId() != null && treeData.getParentId().equals(pid)) {
                rootlist.add(treeData);
            }
        }
        return rootlist;
    }
     /**
      *  递归-----构建子树形结构
      *  @param  treeRootNode 根节点(顶级节点)
      *  @return 整棵树
      */
    private TreeData buildChildTree(TreeData treeRootNode) {
        List<TreeData> childTree = new ArrayList<TreeData>();
        // nodeList:所有节点集合(所有数据)
        nodeList.stream()
                // 判断当前节点的父节点ID是否等于根节点的ID,即当前节点为其下的子节点
                .filter(treeNode->treeNode!=null && treeNode.getParentId() !=null && treeNode.getParentId().equals(treeRootNode.getId()))
                // 再递归进行判断当前节点的情况,调用自身方法
                .forEach(treeData ->childTree.add(buildChildTree(treeData)) );
        // for循环结束,即节点下没有任何节点,树形构建结束,设置树结果
        treeRootNode.setChildren(childTree);
        return treeRootNode;

    }


    /**
     * 递归获取某个父节点下面的所有子节点
     *
     * @param childFolderList 要返回的结果
     * @param folderList  数据库查询出来的所有机构集合
     * @param pid      父id
     *                TODO 注:本身的机构节点  不会  添加进去
     */
    public static void getParentNode(List<InfoVO> childFolderList, List<InfoVO> folderList, String pid) {
        folderList.stream()
                //过滤出父id等于参数的id
                .filter(folder -> folder != null && folder.getParentId() != null  && folder.getParentId().equals(pid))
                .forEach(childFolder -> {
                    //递归遍历下一级
                    getParentNode(childFolderList, folderList, childFolder.getFolderId());
                    //添加
                    childFolderList.add(childFolder);
                });
    }



    /**
     * 递归获取某个子节点的所有父节点
     *
     * @param parentMenu 要返回的结果
     * @param menuList  数据库查询出来的所有机构集合
     * @param folderId        节点id
     *                  TODO   注:本身的机构节点  会  添加进去
     */
    //文件夹递归获取父级
    public static void getFolderParentByChild(List<InfoVO> parentMenu, List<InfoVO> menuList, String folderId) {

        menuList.stream()
                .filter(infoVO -> infoVO != null && folderId != null && infoVO.getFolderId().equals(folderId))
                .forEach(folder -> {
                    getFolderParentByChild(parentMenu, menuList, folder.getParentId());
                    parentMenu.add(folder);
                });

    }
    //部门递归获取父级
    public static void getDeptParentByChild(List<DeptRespDTO> parentMenu, List<DeptRespDTO> menuList, Long deptId) {

        menuList.stream()
                .filter(infoVO -> infoVO != null && deptId != null && infoVO.getId().equals(deptId))
                .forEach(dept -> {
                    getDeptParentByChild(parentMenu, menuList, dept.getParentId());
                    parentMenu.add(dept);
                });

    }


}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值