Java 通过使用递归函数实现树状结构

项目中遇到一个接口,需要根据部门级别返回一个树状结构,包括部门,子部门,和部门下的员工,其结构如下:

{
	"code": 0,
	"data": [{
		"nodeId": 0,
		"label": "第一级部门",
		"choiced": 0,
		"children": [{
			"nodeId": 1,
			"label": "第二级部门",
			"choiced": 1,
			"children": [
                {
					"nodeId": 2,
					"label": "第三级部门",
					"choiced": 0,
					"children": []
				},
				{
					"nodeId": 3,
					"label": "第二级部门的人员",
					"choiced": 1
				}
			]
		}]
	}]
}

仔细分析一下,每一级的结构基本都相同,有"nodeId","label","choiced"这三个基本的信息,需要注意的是,部门有"children"字段,即子部门,而员工没有这个字段。


难点分析:

        这个结构的难点一个在于我们不知道这个部门的结构有几层,普通的循环无法实现这个功能,需要使用递归。另一个难点就是这个结构的children既有部门又有员工,但员工的数据结构与部门的结构又不太一样。

实现思路:

        使用递归的方式遍历部门列表数据,首先获得所有一级部门,然后在每个一级部门,去查找该部门下的二级部门和该部门下的员工......。最底层员工层我们可以写一个父类,然后部门去继承这个类并添一个children属性。

实现方法:

  父类NodeVo:

public class NodeVo {
    //省略get/set方法
    private Integer node_id;
    private String label;
    private Integer choiced;
}

子类AuthTreeVo:

public class AuthTreeVo extends NodeVo{
    //省略get/set方法
    private List<NodeVo> children;
}

 实现类AuthTree:

 构造方法:根据业务需求传参

public AuthTree(List<PersonWithDept> personList,List<PersonWithDept> personAuthList, List<Department> departmentList, List<Department> departmentAuthList){
        this.personList = personList;
        this.personAuthList = personAuthList;
        this.departmentList = departmentList;
        this.departmentAuthList = departmentAuthList;

    }

获取所有一级部门:getRootNode() 

public List<Department> getRootNode(){
        List<Department> departments = new ArrayList<>();
        for(Department department:departmentList){
            if(department.getParentId().equals(0)){
                departments.add(department);
            }
        }
        return departments;
    }

 实现树状结构的方法:makeTree()

public List<AuthTreeVo> makeTree(){
        List<AuthTreeVo> authTreeVos = new ArrayList<>();

        for(Department department:getRootNode()){
            AuthTreeVo authTreeVo = new AuthTreeVo();
            authTreeVo.setNode_id(department.getDepartmentId());
            authTreeVo.setLabel(department.getDepartmentName());

            authTreeVo=loopTree(department);
            authTreeVos.add(authTreeVo);
        }
        return authTreeVos;
    }

递归方法:loopTree()

public AuthTreeVo loopTree(Department department){
        AuthTreeVo authTreeVo = new AuthTreeVo();
        authTreeVo.setNode_id(department.getDepartmentId());
        authTreeVo.setLabel(department.getDepartmentName());
        authTreeVo.setChoiced(0);
        for(Department authDepartment: departmentAuthList) {
            if (authDepartment.getDepartmentId().equals(department.getDepartmentId())) {
                authTreeVo.setChoiced(1);
                break;
            }
        }

        List<NodeVo> authTreeVos = new ArrayList<>();

        for(Department departmentChild:departmentList){
            if(departmentChild.getParentId().equals(department.getDepartmentId())){
                authTreeVos.add(loopTree(departmentChild));
            }
        }

            for(PersonWithDept person: personList){
                if(person.getDepartmentId().equals(department.getDepartmentId())){
                    NodeVo nodeVo = new NodeVo();
                    nodeVo.setNode_id(person.getPersonId());
                    nodeVo.setLabel(person.getName());
                    nodeVo.setChoiced(0);
                    for(PersonWithDept authPerson:personAuthList){
                        if(authPerson.getPersonId().equals(person.getPersonId())){
                            nodeVo.setChoiced(1);
                            break;
                        }
                    }
                    authTreeVos.add(nodeVo);
                }
            }

        authTreeVo.setChildren(authTreeVos);
        return authTreeVo;
    }

/** * 根据等级查询类目树 * * @param level * @return */ @Override public List queryCategoryTree(Integer level) { //查询当前级别下类目 List list = categoryDAO.list(level); //组装好的类目树,返回前端 List categoryTree = new ArrayList(); //所有类目 List allDTOList = new ArrayList(); if (CollectionUtils.isEmpty(list)) { return categoryTree; } for (CategoryDO categoryDO : list) { allDTOList.add(new CategoryTreeDTO().convertDOToDTO(categoryDO)); } //当前等级类目 categoryTree = allDTOList.stream().filter(dto -> level.equals(dto.getLevel())).collect(Collectors.toList()); for (CategoryTreeDTO categoryTreeDTO : categoryTree) { //组装类目为树结构 assembleTree(categoryTreeDTO, allDTOList,Constants.CATEGORY_MAX_LEVEL - level); } return categoryTree; } /** * 组装树 * * @param categoryTreeDTO * @param allList * @param remainRecursionCount 剩余递归次数 * @return */ public CategoryTreeDTO assembleTree(CategoryTreeDTO categoryTreeDTO, List allList, int remainRecursionCount) { remainRecursionCount--; //最大递归次数不超过Constants.CATEGORY_MAX_LEVEL-level次,防止坏数据死循环 if(remainRecursionCount < 0){ return categoryTreeDTO; } String categoryCode = categoryTreeDTO.getCategoryCode(); Integer level = categoryTreeDTO.getLevel(); //到达最后等级树返回 if (Constants.CATEGORY_MAX_LEVEL == level) { return categoryTreeDTO; } //子类目 List child = allList.stream().filter(a -> categoryCode.equals(a.getParentCode())).collect(Collectors.toList()); if (null == child) { return categoryTreeDTO; } categoryTreeDTO.setChildren(child); //组装子类目 for (CategoryTreeDTO dto : child) { assembleTree(dto, allList,remainRecursionCount); } return categoryTreeDTO; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值