Java实现树形结构和递归查询

树形结构的数据一般是利用类似于id和parent_id之前的关系来构造,以部门为例,当前部门的信息中需要知道自己的部门编号和上一级的部门编号,才能构造出树形结构的数据,先准备好能够构造树形结构的数据

{
  "deptList": [
    {
      "deptCode": "PRODUCT_DEPT",
      "deptName": "产品研发部",
      "deptDesc": "负责各类产品的研发工作支持",
      "createDate": "2023-10-15",
      "parentDeptCode": ""
    },
    {
      "deptCode": "DR_DEPT",
      "deptName": "市场调研部",
      "deptDesc": "负责产品功能的市场调研与分析",
      "createDate": "2023-10-20",
      "parentDeptCode": ""
    },
    {
      "deptCode": "AI_DEPT",
      "deptName": "人工智能研发部",
      "deptDesc": "开发智能服务",
      "createDate": "2023-10-18",
      "parentDeptCode": ""
    },
    {
      "deptCode": "IFS_DEPT",
      "deptName": "金融服务部",
      "deptDesc": "负责金融产品的对外运营服务,售后服务等",
      "createDate": "2023-10-15",
      "parentDeptCode": ""
    },
    {
      "deptCode": "CORE_DATA_DEPT",
      "deptName": "数据中心部",
      "deptDesc": "负责管理维护核心数据平台",
      "createDate": "2023-10-15",
      "parentDeptCode": "PRODUCT_DEPT"
    },
    {
      "deptCode": "CDP_DATA_DEPT",
      "deptName": "中台数据部",
      "deptDesc": "负责管理维护中台数据",
      "createDate": "2023-10-15",
      "parentDeptCode": "CORE_DATA_DEPT"
    },
    {
      "deptCode": "CDP_DATA_DEV_GROUP",
      "deptName": "中台数据开发组",
      "deptDesc": "负责中台数据开发工作",
      "createDate": "2023-10-15",
      "parentDeptCode": "CDP_DATA_DEPT"
    },
    {
      "deptCode": "CDP_DATA_TEST_GROUP",
      "deptName": "中台数据测试组",
      "deptDesc": "负责中台数据测试工作",
      "createDate": "2023-10-15",
      "parentDeptCode": "CDP_DATA_DEPT"
    },
    {
      "deptCode": "CLOUD_DATA_DEPT",
      "deptName": "云端数据部",
      "deptDesc": "负责管理维护云端数据",
      "createDate": "2023-10-15",
      "parentDeptCode": "CORE_DATA_DEPT"
    },
    {
      "deptCode": "CLOUD_DATA_DEVOPS_GROUP",
      "deptName": "云端数据运维组",
      "deptDesc": "负责云端数据运维工作",
      "createDate": "2023-10-15",
      "parentDeptCode": "CLOUD_DATA_DEPT"
    },
    {
      "deptCode": "CS_DEVOPS_GROUP",
      "deptName": "长沙运维组",
      "deptDesc": "负责云端数据运维工作",
      "createDate": "2023-10-15",
      "parentDeptCode": "CLOUD_DATA_DEVOPS_GROUP"
    },
    {
      "deptCode": "PAAS_DATA_DEPT",
      "deptName": "平台数据部",
      "deptDesc": "负责管理维护平台数据",
      "createDate": "2023-10-15",
      "parentDeptCode": "CORE_DATA_DEPT"
    },
    {
      "deptCode": "PC_PRODUCT_DEPT",
      "deptName": "PC端产品部",
      "deptDesc": "负责PC终端产品的研发工作支持",
      "createDate": "2023-10-15",
      "parentDeptCode": "PRODUCT_DEPT"
    },
    {
      "deptCode": "MOBILE_DEPT",
      "deptName": "移动端产品部",
      "deptDesc": "负移动终端产品的研发工作支持",
      "createDate": "2023-10-15",
      "parentDeptCode": "PRODUCT_DEPT"
    },
    {
      "deptCode": "IFS_EXTEND_DEPT",
      "deptName": "金融推广部",
      "deptDesc": "负责金融产品的推广",
      "createDate": "2023-10-15",
      "parentDeptCode": "IFS_DEPT"
    },
    {
      "deptCode": "IFS_AFTER_SALE_DEPT",
      "deptName": "金融售后部",
      "deptDesc": "负责金融产品的售后服务",
      "createDate": "2023-10-15",
      "parentDeptCode": "IFS_DEPT"
    },
    {
      "deptCode": "AI_ROBOT_DEPT",
      "deptName": "人工智能机器人部",
      "deptDesc": "负责智能机器人的功能设计和维护",
      "createDate": "2023-10-18",
      "parentDeptCode": "AI_DEPT"
    },
    {
      "deptCode": "AI_ROBOT_DEV_GROUP",
      "deptName": "机器人开发组",
      "deptDesc": "负责智能机器人的开发",
      "createDate": "2023-10-18",
      "parentDeptCode": "AI_ROBOT_DEPT"
    },
    {
      "deptCode": "AI_ROBOT_IMP_GROUP",
      "deptName": "机器人实施组",
      "deptDesc": "负责智能机器人的安装实施",
      "createDate": "2023-10-18",
      "parentDeptCode": "AI_ROBOT_DEPT"
    }
  ]
}

部门的基础实体和部门树实体

package com.yx.basejv.entity;

import lombok.Data;

@Data
public class Dept {
    private String deptCode;
    private String deptName;
    private String deptDesc;
    private String createDate;
    private String parentDeptCode;
}
package com.yx.basejv.vo;

import com.yx.basejv.entity.Dept;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

@Data
public class DeptTreeVo extends Dept {
    private List children = new ArrayList<>();
}

编写一个测试类运行查看效果

package com.yx.basejv;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.yx.basejv.entity.Dept;
import com.yx.basejv.vo.DeptTreeVo;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.junit.platform.commons.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

public class BizFeatureTest {

    private final static String DEPT_INFO_PATH = "src/main/resources/deptInfo.json";
    private final static String DEPT_TREE_PATH = "src/test/resources/out/deptTree.json";

    /**
     * 构造部门树形结构返回数据
     *
     * @throws IOException
     */
    @Test
    public void buildDeptTreeTest() throws IOException {
        File file = new File(DEPT_INFO_PATH);
        String comment = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
        JSONObject jsonObject = Optional.ofNullable(JSON.parseObject(comment)).orElse(new JSONObject());
        List deptList = JSON.parseArray(JSON.toJSONString(jsonObject.get("deptList")), DeptTreeVo.class);

        //筛选存在父节点的数据
        Map> childrenMap = deptList.parallelStream().filter(d -> !StringUtils.isBlank(d.getParentDeptCode())).collect(Collectors.groupingBy(DeptTreeVo::getParentDeptCode));
        //将指定的部门集合赋值到对应的父节点下
        deptList.forEach(d -> {
            if (childrenMap.containsKey(d.getDeptCode())) {
                d.setChildren(childrenMap.get(d.getDeptCode()));
            }
        });
        //筛选没有父节点的数据
        List treeVoList = deptList.parallelStream().filter(d -> StringUtils.isBlank(d.getParentDeptCode())).collect(Collectors.toList());

        JSONObject returnJson = new JSONObject();
        returnJson.put("deptTree", treeVoList);
        File outFile = new File(DEPT_TREE_PATH);
        //设置json的格式
//        String json = JSON.toJSONString(returnJson, SerializerFeature.PrettyFormat,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat, SerializerFeature.WriteNullListAsEmpty);
        String json = JSON.toJSONString(returnJson, SerializerFeature.PrettyFormat);
        FileUtils.write(outFile, json, "UTF-8");
    }

    /**
     * 查询指定节点下的所有部门
     *
     * @throws IOException
     */
    @Test
    public void fuzzyQueryDeptTreeTest() throws IOException {
        File file = new File(DEPT_INFO_PATH);
        String comment = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
        JSONObject jsonObject = Optional.ofNullable(JSON.parseObject(comment)).orElse(new JSONObject());
        List deptList = JSON.parseArray(JSON.toJSONString(jsonObject.get("deptList")), Dept.class);
        Map> allChildrenMap = deptList.stream().filter(vo -> !StringUtils.isBlank(vo.getParentDeptCode())).collect(Collectors.groupingBy(Dept::getParentDeptCode));
        List> treeLists = new ArrayList<>();
        Set portCodeSet = new HashSet<>();
        if (allChildrenMap.containsKey("PRODUCT_DEPT")) {
            treeLists.add(allChildrenMap.get("PRODUCT_DEPT"));
            recursionPortCode(allChildrenMap, treeLists, portCodeSet);
        }
        System.out.println(String.join(",", portCodeSet));
    }

    /**
     * 递归获取下级部门编号
     * @param allChildrenMap
     * @param treeLists
     * @param portCodeSet
     */
    private void recursionPortCode(Map> allChildrenMap, List> treeLists, Set portCodeSet) {
        boolean isContinue = false;
        List> nodeLists = new ArrayList<>();
        for (List voList : treeLists) {
            for (Dept vo : voList) {
                if (allChildrenMap.containsKey(vo.getDeptCode())) {
                    isContinue = true;
                    nodeLists.add(allChildrenMap.get(vo.getDeptCode()));
                }
                portCodeSet.add(vo.getDeptCode());
            }
        }

        if (isContinue) {
            recursionPortCode(allChildrenMap, nodeLists, portCodeSet);
        }
    }
}

你可能感兴趣的:(Java概要,java)