树形结构的数据一般是利用类似于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);
}
}
}