java 递归删除树节点

需求:按组织树和岗位树查询。(组织org 和岗位都在机构下)

问题是:机构树查询出来的是全部的组织机构,需求是按人员所在机构,岗位展示树(把不在学员列表多余的组织和岗位节点删除):

java 递归删除树节点_第1张图片

 java 递归删除树节点_第2张图片

 java 递归删除树节点_第3张图片

上图可理解如下图: nodepath 会显示当前节点的所有父节点:nodePath=1785.1786.1787.1788

如标记的无效节点为:

2021-12-02 13:20:06.117  INFO 40468 --- [qtp335196473-36] c.g.b.m.service.impl.AgencyServiceImpl   : invalidPostList:[PostTreeResponse(id=1785, name=默认岗位组, title=默认岗位组, key=1785, level=1, postType=group, userNum=4, nodePath=1785, parentId=0, disabled=true, children=[PostTreeResponse(id=1786, name=默认岗位组, title=默认岗位组, key=1786, level=2, postType=group, userNum=4, nodePath=1785.1786, parentId=1785, disabled=true, children=[PostTreeResponse(id=1787, name=默认岗位组, title=默认岗位组, key=1787, level=3, postType=group, userNum=4, nodePath=1785.1786.1787, parentId=1786, disabled=true, children=[PostTreeResponse(id=1788, name=默认岗位, title=默认岗位, key=1788, level=4, postType=post, userNum=4, nodePath=1785.1786.1787.1788, parentId=1787, disabled=false, children=[])])])]), PostTreeResponse(id=1801, name=高顿机构, title=高顿机构, key=1801, level=1, postType=group, userNum=40, nodePath=1801, parentId=0, disabled=true, children=[PostTreeResponse(id=1802, name=高顿机构, title=高顿机构, key=1802, level=2, postType=post, userNum=40, nodePath=1801.1802, parentId=1801, disabled=false, children=[])]), PostTreeResponse(id=9502, name=哈哈哈, title=哈哈哈, key=9502, level=1, postType=group, userNum=2, nodePath=9502, parentId=0, disabled=true, children=[PostTreeResponse(id=9503, name=发发发, title=发发发, key=9503, level=2, postType=post, userNum=2, nodePath=9502.9503, parentId=9502, disabled=false, children=[])])]
 

 

/**
     * @Title: 根据班级id批量查询学员岗位
     * @Author: ken
     * @Description:
     * @Date: 2021/9/17  19:41
     * @Param: [gradeId]
     * @return com.gaodun.bcloud.mstat.response.BaseResponse>
     **/
    @Override
    public BaseResponse> getPostListByGradeId(Long gradeId) {
       BaseResponse> result = agencySvcClient.getPostListByAgencyIdList(gradeMemberRepository.findAgencyIdsByGradeId(gradeId));
        List agencyPostResponseList = result.getResult();
        if(CollectionUtils.isEmpty(agencyPostResponseList)) {
            return BaseResponse.failureEnum(HttpErrorCodes.NO_DATA);
        }
        List userIdList = gradeMemberRepository.findAllByGradeId(gradeId);
        Pageable pageable = PageUtil.getPageable(1, Constants.DEFAULT_MAX_PAGE_SIZE);
        Page userInfoPage = agcUsersEntityRepository.findPageByCondition(userIdList, null, null,
                null, null, pageable);
        if (Objects.isNull(userInfoPage) || CollectionUtils.isEmpty(userInfoPage.getContent())) {
            return BaseResponse.failureEnum(HttpErrorCodes.NO_DATA);
        }

        List content = userInfoPage.getContent();
        Set postIdSet = content.stream().map(BaseUserInfoDTO::getPostId).filter(Objects::nonNull).collect(Collectors.toSet());
        // 查找岗位节点
        List postList = postListRepository.findAllAgcPostList(postIdSet);
        if(CollectionUtils.isEmpty(postList)){
            return BaseResponse.failureEnum(HttpErrorCodes.NO_DATA);
        }

        List nodePathList = postList.stream().map(AgcPostListEntity::getNodePath).collect(Collectors.toList());

        // 标记删除节点
        List invalidPostList = Lists.newArrayList();
        for (AgencyPostResponse agencyPostResponse : agencyPostResponseList) {
            List postTreeResponseList = agencyPostResponse.getPost();
            markDelPostNode(nodePathList, postTreeResponseList, invalidPostList);
        }
        log.info("invalidPostList:{}",invalidPostList.toString());

        // 删除节点
        for(PostTreeResponse invalidNode: invalidPostList) {
            for (AgencyPostResponse agencyPostResponse : agencyPostResponseList) {
                List postTreeResponseList = agencyPostResponse.getPost();
                deletePostNode(invalidNode, postTreeResponseList);
            }
        }
        agencyPostResponseList.removeIf(s -> CollectionUtils.isEmpty(s.getPost()));

        return BaseResponse.success(agencyPostResponseList);
    }

    /**
     * @Title: 根据机构id批量查询学员组织
     * @Author: ken
     * @Description: 遍历traverse
     * @Date: 2021/9/17  19:57
     * @Param: [gradeId]
     * @return com.gaodun.bcloud.mstat.response.BaseResponse>
     **/
    @Override
    public BaseResponse> getOrganizationListByGradeId(Long gradeId) {
        List userIdList = gradeMemberRepository.findAllByGradeId(gradeId);
        //批量查询用户组织(部门)信息
        List userOrganizationDTOList = agcUserOrganizationRepository.findByUserIdsOrAgencyId(userIdList, null);
        if(CollectionUtils.isEmpty(userOrganizationDTOList)){
            return BaseResponse.failureEnum(HttpErrorCodes.NO_DATA);
        }
        //查询用户组织树
        Set orgIds = userOrganizationDTOList.stream().map(i -> i.getOrgId()).collect(Collectors.toSet());

        BaseResponse> result = agencySvcClient.getOrganizationListByAgencyIdList(gradeMemberRepository.findAgencyIdsByGradeId(gradeId));
        if(Objects.isNull(result) || CollectionUtils.isEmpty(result.getResult())){
            return BaseResponse.failureEnum(HttpErrorCodes.NO_DATA);
        }

        List agencyOrganizationResponseList = result.getResult();
        // 查找学员组织节点
        List nodePathList = Lists.newArrayList();
        for(Long orgId: orgIds) {
            for (AgencyOrganizationResponse agencyOrganizationResponse : agencyOrganizationResponseList) {
                List organizationList = agencyOrganizationResponse.getOrganization();
                traverseOrgTree(nodePathList, orgId, organizationList);
            }
        }

        // 标记删除节点
        List invalidNodeList = Lists.newArrayList();
        for (AgencyOrganizationResponse agencyOrganizationResponse : agencyOrganizationResponseList) {
            List organizationList = agencyOrganizationResponse.getOrganization();
            markDelOrgNode(nodePathList, organizationList, invalidNodeList);
        }
        //log.info("invalidNodeList:{}",invalidNodeList.toString());

        // 删除节点
        for(OrganizationResponse invalidNode: invalidNodeList) {
            for (AgencyOrganizationResponse agencyOrganizationResponse : agencyOrganizationResponseList) {
                List organizationList = agencyOrganizationResponse.getOrganization();
                deleteOrgNode(invalidNode, organizationList);
            }
        }
        //log.info("agencyOrganizationResponseList:{}",agencyOrganizationResponseList.toString());
        return BaseResponse.success(agencyOrganizationResponseList);
    }

    /**
     * @Title: 遍历树
     * @Author: ken
     * @Description:
     * @Date: 2021/12/2  10:35
     * @Param: [nodePathList, orgId, organizationList]
     * @return void
     **/
    private void traverseOrgTree(List nodePathList, Long orgId, List organizationList) {
        for(OrganizationResponse organizationResponse :organizationList){
            if(organizationResponse.getNodePath().endsWith(String.valueOf(orgId))){
                nodePathList.add(organizationResponse.getNodePath());
                continue;
            }else if(CollectionUtils.isEmpty(organizationResponse.getChildren())){
                continue;
            }else{
                traverseOrgTree(nodePathList,orgId,organizationResponse.getChildren());
            }
        }
    }

    /**
     * @Title: 标记无效节点
     * @Author: ken
     * @Description:
     * @Date: 2021/12/2  10:34
     * @Param: [nodePathList, organizationList, invalidNodeList]
     * @return void
     **/
    private void markDelOrgNode(List nodePathList, List organizationList, List invalidNodeList) {
        for(OrganizationResponse organizationResponse : organizationList){
            // 是否在路径标识
            boolean pathFlag = nodePathList .stream().anyMatch(x-> x.startsWith(organizationResponse.getNodePath()));
            if(!pathFlag){
                invalidNodeList.add(organizationResponse);
                continue;
            }else if(CollectionUtils.isEmpty(organizationResponse.getChildren())){
                continue;
            }else{
                markDelOrgNode(nodePathList,organizationResponse.getChildren(),invalidNodeList);
            }
        }
    }

    /**
     * @Title: 删除节点
     * @Author: ken
     * @Description:
     * @Date: 2021/12/2  10:34
     * @Param: [invalidNode, organizationList]
     * @return void
     **/
    private void deleteOrgNode(OrganizationResponse invalidNode, List organizationList) {
        for(OrganizationResponse organizationResponse :organizationList){
            //找到父节点
            if(organizationResponse.getId().equals(invalidNode.getParentId())){
                List childList = organizationResponse.getChildren();
                //移除无效节点
                childList.removeIf(s -> s.getId().equals(invalidNode.getId()));
                organizationResponse.setChildren(childList);
                continue;
            }else if(CollectionUtils.isEmpty(organizationResponse.getChildren())){
                continue;
            }else{
                deleteOrgNode(invalidNode, organizationResponse.getChildren());
            }
        }
    }
    /**
     * @Title: 遍历过滤组织(部门)树
     * @Author: ken
     * @Description:
     * @Date: 2021/12/1  11:12
     * @Param: [orgId, organizationList]
     * @return java.util.List
     **/
    private List traverseOrgTree(Long orgId, List organizationList,
                                                       List organizationResponseLists) {
        for(OrganizationResponse organizationResponse : organizationList){
            if(orgId.equals(organizationResponse.getId())){
                organizationResponse.setChildren(null);
                organizationResponseLists.add(organizationResponse);
            }else if(!CollectionUtils.isEmpty(organizationResponse.getChildren())){
                traverseOrgTree(orgId, organizationResponse.getChildren(),organizationResponseLists);
            }else{
                log.info("@@ no node");
            }
        }
        return organizationResponseLists;
    }

    /**
     * @Title: 标记无效节点
     * @Author: ken
     * @Description:
     * @Date: 2021/12/2  13:18
     * @Param: [nodePathList, postTreeResponseList, invalidPostList]
     * @return void
     **/
    private void markDelPostNode(List nodePathList, List postTreeResponseList, List invalidPostList) {
        for(PostTreeResponse postTreeResponse :postTreeResponseList){
            // 是否在路径标识
            boolean pathFlag = nodePathList .stream().anyMatch(x-> x.startsWith(postTreeResponse.getNodePath()));
            if(!pathFlag){
                invalidPostList.add(postTreeResponse);
                continue;
            }else if(CollectionUtils.isEmpty(postTreeResponse.getChildren())){
                continue;
            }else{
                markDelPostNode(nodePathList,postTreeResponse.getChildren(),invalidPostList);
            }
        }
    }

    /**
     * @Title: 删除无效节点
     * @Author: ken
     * @Description:
     * @Date: 2021/12/2  13:18
     * @Param: [invalidNode, postTreeResponseList]
     * @return void
     **/
    private void deletePostNode(PostTreeResponse invalidNode, List postTreeResponseList) {
        //对于没有父节点的 特殊处理
        postTreeResponseList.removeIf(s -> s.getParentId().equals(0L) && s.getNodePath().equals(invalidNode.getNodePath()));
        if(CollectionUtils.isEmpty(postTreeResponseList)){
            return;
        }
        for(PostTreeResponse postTreeResponse :postTreeResponseList){
            //对于没有父节点的
            postTreeResponseList.removeIf(s -> s.getParentId().equals(0L) && s.getNodePath().equals(invalidNode.getNodePath()));
            //找到父节点
            if(postTreeResponse.getId().equals(invalidNode.getParentId())){
                List childList = postTreeResponse.getChildren();
                //移除无效节点
                childList.removeIf(s -> s.getId().equals(invalidNode.getId()));
                postTreeResponse.setChildren(childList);
                continue;
            }else if(CollectionUtils.isEmpty(postTreeResponse.getChildren())){
                continue;
            }else{
                deletePostNode(invalidNode, postTreeResponse.getChildren());
            }
        }
    }

核心思路:

        ① 找到节点 

        ② 标记删除的节点

        ③ 删除节点。(切断当前节点跟父节点的联系,注意判断是否是父节点)

最终效果图:

java 递归删除树节点_第4张图片

java 递归删除树节点_第5张图片

你可能感兴趣的:(java8,java,数据结构,java,递归算法,数据结构,后端)