Java扁平数据树型化
2021-04-01 本文已影响0人
大黑跟小白的日常
image.png
image.png
一个学生碰到的面试题,比较经典,企业使用率较高,这里做一下记录。
具体代码如下
// 业务展示层实体
class DepartmentVO extends Department {
List<DepartmentVO> departmentVOList;
public List<DepartmentVO> getDepartmentVOList() {
return departmentVOList;
}
public void setDepartmentVOList(List<DepartmentVO> departmentVOList) {
this.departmentVOList = departmentVOList;
}
}
// 数据库实体
class Department {
private Integer id;
private String name;
private Integer pid;
public Department() {
}
public DepartmentVO parse2VO() {
DepartmentVO departmentVO = new DepartmentVO();
departmentVO.setName(this.name);
departmentVO.setId(this.id);
departmentVO.setPid(this.pid);
return departmentVO;
}
public Department(Integer id, String name, Integer pid) {
this.id = id;
this.name = name;
this.pid = pid;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPid() {
return pid;
}
public void setPid(Integer pid) {
this.pid = pid;
}
}
测试
public static void main(String[] args) {
//初始化测试数据
List<Department> list = new ArrayList<>();
list.add(new Department(100101, "后台开发部门", 1001));
list.add(new Department(100102, "前台开发部门", 1001));
list.add(new Department(100103, "测试部门", 1001));
list.add(new Department(1001, "研发部", 10));
list.add(new Department(1002, "财务部", 10));
list.add(new Department(1003, "人事部", 10));
list.add(new Department(10, "总裁办", null));
// ...
// 获取节点ID及其儿子们的map映射关系,方便后续使用
HashMap<Integer, List<Department>> map = new HashMap<>();// 父节点id 及父节点下集合 map
list.forEach(department -> {
List<Department> departments = map.get(department.getPid());
if (departments == null) {
departments = new ArrayList<>();
map.put(department.getPid(), departments);
}
departments.add(department);
});
List<Department> rootDepts = map.get(null);
if(CollectionUtils.isEmpty(rootDepts) || rootDepts.size()>1){
throw new RuntimeException("数据错误");
}
// 获取根节点
Department department = rootDepts.get(0);
DepartmentVO rootDept = department.parse2VO();
// 获取完整根节点(含子项)
DepartmentVO departmentVO = treeDeptList(rootDept, map);
System.out.println(departmentVO);
}
核心方法
/**
* @Author G_Y
* @Description: 根据当前节点 递归获取其子节点并设置其中
* @Date 2021/4/1 17:22
* map:// 父节点id 及父节点下集合 的映射 map
**/
public static DepartmentVO treeDeptList(DepartmentVO departmentVO, Map<Integer, List<Department>> map) {
Integer id = departmentVO.getId();// 当前节点id
List<Department> sons = map.get(id);// 以当前节点id作为父节点的子节点集合
if (sons == null) {
// 如果不存在子节点,则不需要再操作
return departmentVO;
}
// 如果存在则需要 将 字节点 加入到 当前节点的 departmentVOList 属性中
ArrayList<DepartmentVO> departmentVOSList = new ArrayList<>();
departmentVO.setDepartmentVOList(departmentVOSList);
for (Department son : sons) {
DepartmentVO sonVO = son.parse2VO();
departmentVOSList.add(sonVO);
// 使用递归 补全 sonVO节点下的 子集合 属性
sonVO = treeDeptList(sonVO, map);
}
return departmentVO;
}
结果演示
image.png
json转换结果展示:
{
"id": 10,
"name": "总裁办",
"departmentVOList": [{
"id": 1001,
"name": "研发部",
"pid": 10,
"departmentVOList": [{
"id": 100101,
"name": "后台开发部门",
"pid": 1001
}, {
"id": 100102,
"name": "前台开发部门",
"pid": 1001
}, {
"id": 100103,
"name": "测试部门",
"pid": 1001
}]
}, {
"id": 1002,
"name": "财务部",
"pid": 10
}, {
"id": 1003,
"name": "人事部",
"pid": 10
}]
}