概要

本文主要记录在树形结构中会遇到的问题,
使用部门结构讲解,main方法进行演示。

1、获取部门树结构
2、根据部门id获取所有下级
3、根据部门id获取上级部门
4、根据部门id获取类似面包屑(总公司/技术部/技术一部)

对象结构示例

@Data
static class Department{
    Integer id;
    String name;
    Integer parentId;
}

可能会用到的依赖(非必要)

<dependency>
   <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.28</version>
</dependency>

完整示例

package com.example.springboot_demo;

import com.alibaba.fastjson.JSONObject;
import lombok.Data;

import java.util.*;
import java.util.stream.Collectors;

public class TreeTest {
    public static void main(String[] args) {

        List<DepartmentVO> departments = Arrays.asList(
                new DepartmentVO(1, "总公司", 0),
                new DepartmentVO(2, "技术部", 1),
                new DepartmentVO(3, "技术一部", 2),
                new DepartmentVO(4, "技术二部", 2),
                new DepartmentVO(5, "业务部", 1),
                new DepartmentVO(6, "业务一组", 5),
                new DepartmentVO(7, "业务二组", 5),
                new DepartmentVO(8, "业务二组一部", 7)
        );

        //根据id获取所有下级
        List<DepartmentVO> subList = new ArrayList<>();
        getSubList(2,departments,subList);
        System.out.println(JSONObject.toJSON(subList));

        //根据id获取所有上级
        List<DepartmentVO> supList = new ArrayList<>();
        findSupList(3,departments,supList);
        System.out.println(JSONObject.toJSON(supList));

        //根据id获取所有上级名字 类似面包屑结构 总公司/技术部/技术一部
        StringBuilder sb = new StringBuilder();
        findSupName(3,departments,sb);
        System.out.println(sb);

        //返回部门树形结构
        List<DepartmentVO> departmentVOS = buildTree(departments);
        System.out.println(JSONObject.toJSON(departmentVOS));
    }

    static List<DepartmentVO> buildTree(List<DepartmentVO> departments){

        //构建根节点
        List<DepartmentVO> rootNode = departments.stream().filter(i -> Objects.equals(i.getParentId(), 0)).collect(Collectors.toList());

        //用根节点去递归找到child
        for (DepartmentVO department : rootNode) {
            department.setChild(buildTree(department.getId(), departments));
        }

        return rootNode;
    }

    static List<DepartmentVO> buildTree(Integer deptId, List<DepartmentVO> departments){

        List<DepartmentVO> childList = new ArrayList<>();
        for (DepartmentVO dept : departments) {
            // 遍历所有属于父级节点的子节点
            if (Objects.equals(deptId, dept.getParentId())) {
                childList.add(dept);
            }
        }

        //然后给所有子节点添加子节点
        for (DepartmentVO dept : childList) {
            // 遍历所有属于父级节点的子节点
            dept.setChild(buildTree(dept.getId(), departments));
        }

        return childList;
    }

    //根据部门id查找所有下级部门
    static void getSubList(Integer id, List<DepartmentVO> departments, List<DepartmentVO> result) {
        for (DepartmentVO departmentVO : departments) {
            if (Objects.equals(departmentVO.getParentId(), id)) {
                getSubList(departmentVO.getId(), departments, result);
                result.add(departmentVO);
            }
        }
    }

    //根据部门id 获取所有上级
    static void findSupList(Integer deptId, List<DepartmentVO> departments, List<DepartmentVO> result){
        DepartmentVO departmentVO = departments.stream().filter(i -> Objects.equals(deptId, i.getId())).findFirst().orElse(null);
        if (departmentVO == null) {
            return;
        }
        findSupList(departmentVO.getParentId(), departments, result);
        result.add(departmentVO);
    }


    // 如 总公司/技术部/技术一部
    static void findSupName(Integer deptId, List<DepartmentVO> departments, StringBuilder sb){
        DepartmentVO departmentVO = departments.stream().filter(i -> Objects.equals(deptId, i.getId())).findFirst().orElse(null);
        if (departmentVO == null) {
            return;
        }
        findSupName(departmentVO.getParentId(), departments, sb);
        if(sb.length() > 0){
            sb.append("/");
        }
        sb.append(departmentVO.getName());
    }


    @Data
    static class DepartmentVO{
        Integer id;
        String name;
        Integer parentId;

        List<DepartmentVO> child;

        public DepartmentVO(Integer id, String name, Integer parentId) {
            this.id = id;
            this.name = name;
            this.parentId = parentId;
        }
    }

}

控制台输出:

根据id获取所有下级:[{"name":"技术一部","id":3,"parentId":2},{"name":"技术二部","id":4,"parentId":2}]
根据id获取所有上级:[{"name":"总公司","id":1,"parentId":0},{"name":"技术部","id":2,"parentId":1},{"name":"技术一部","id":3,"parentId":2}]
根据id获取所有上级名字:总公司/技术部/技术一部
返回部门树形结构:[{"name":"总公司","id":1,"parentId":0,"child":[{"name":"技术部","id":2,"parentId":1,"child":[{"name":"技术一部","id":3,"parentId":2,"child":[]},{"name":"技术二部","id":4,"parentId":2,"child":[]}]},{"name":"业务部","id":5,"parentId":1,"child":[{"name":"业务一组","id":6,"parentId":5,"child":[]},{"name":"业务二组","id":7,"parentId":5,"child":[{"name":"业务二组一部","id":8,"parentId":7,"child":[]}]}]}]}]

小结

对于树形结构、结构都是大同小异,具体的场景还需要进行对应的校验。

如果数据量庞大时、建议把List替换为Map结构。处理更快。

10-07 21:25