entity结构
现在有一个目录WorkAppendixDirectory,它的结构如下:
public class WorkAppendixDirectory extends BaseEntity {
private static final long serialVersionUID = 1L;
private String name;
private Long parent;
private String remark;
}
现在我们数据库表里存了很多该结构的记录:
而在前台展示时我们想要这种效果:
聪明的你应该想到了,每条子目录都应该在Long parent存上其父亲的id,用来指引孩子目录的父亲目录。每条父亲目录应该以某种方式存储所有孩子目录,那么应该以何种方式呢?
TreeData结构
我们建立一个TreeData结构,他的属性有WorkAppendixDirectory 里所有的属性,并且有一个List结合来存储所有子节点,具体代码和注释:
package com.loongxi.license.utils;
import com.loongxi.license.entity.WorkAppendix;
import com.loongxi.license.entity.WorkAppendixDirectory;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.poi.ss.formula.functions.T;
import java.util.ArrayList;
import java.util.List;
/**
* @projectName: simple_license_serve
* @package: com.loongxi.license.utils
* @className: AppendixDirectoryTreeData
* @author: shicheng Pang
* @description: 附件目录的Tree化,用来将父和子目录转化成Tree型结构。
* 包含4个方法,按循序分别为 :
* 1.将存所有子目录的list转化为TreeData结构
* 2.将存所有父目录的list转化为TreeData结构
* 3.将父和子的TreeDataList转化为对应好的Tree(遍历每一个父节点,并调用方法4获得该父亲的所有孩子节点)
* 4.给定一个存储所有子节点的list和一个指定父节点(这两个参数从方法3中传入),递归寻找该父节点的所有子节点,
* 将查出的孩子字节点保存至 List<TreeData> child 里,
* @date: 2022/8/23 11:25
* @version: 1.0
*/
public class AppendixDirTreeData {
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class TreeData{
private List<TreeData> children;
private Long id;
private String name;
private Long parent;
private String remark;
//方法1 将存储子目录的list转化为存储子节点的list
public static List convertedAppendixDirToChildTree(List<WorkAppendixDirectory> dirChildList){
List<TreeData> childList = new ArrayList<>();
for (WorkAppendixDirectory dir:dirChildList){
TreeData treeData=new TreeData();
treeData.setName(dir.getName());
treeData.setId(dir.getId());
treeData.setRemark(dir.getRemark());
treeData.setParent(dir.getParent());
childList.add(treeData);
}
return childList;
}
//方法2 将存储父目录的list转化为存储父节点的list
public static List convertedAppendixDirToFatherTree(List<WorkAppendixDirectory> dirFatherList){
List<TreeData> fatherList = new ArrayList<>();
for (WorkAppendixDirectory dir:dirFatherList){
TreeData treeData=new TreeData();
treeData.setName(dir.getName());
treeData.setId(dir.getId());
treeData.setRemark(dir.getRemark());
treeData.setParent(dir.getParent());
fatherList.add(treeData);
}
return fatherList;
}
//方法3 获取这个树
public static List<TreeData> getTree(List<TreeData> allChildList,List<TreeData> fatherList){
//循环顶级父节点数据,目的是在每一个父级树节点中装填对应的子节点数据
List<TreeData> data_tree = new ArrayList<TreeData>();
// 递归装填数据
for (TreeData treeData : fatherList) {
data_tree.add(getChildNode(allChildList, treeData));
}
return data_tree;
}
//方法4 给定一个存储所有子节点的list和一个指定父节点,递归寻找该父节点的所在这里插入代码片有子节点,将查出的字节点保存至 List<TreeData> child 里
private static TreeData getChildNode(List<TreeData> allChildList, TreeData fatherTree) {
List<TreeData> childTree=new ArrayList<>();
for (TreeData treeData : allChildList) {
if (treeData.getParent().equals(fatherTree.getId())) {
childTree.add(treeData);
fatherTree.setChildren(childTree);
//fatherTree.getChildren().add(treeData);//将该字节点添加至该父节点的children里
getChildNode(allChildList, treeData);//注意这里
}
}
return fatherTree;
}
}
}
获得Tree
在对应controller里调用刚才的静态方法:
/**
* 获取所有目录,并以树的形式
*/
@GetMapping("/getDirectoryByTree")
@ApiOperationSupport(order = 2)
@ApiOperation(value = "分页", notes = "")
public R getDirectoryByTree() {
List<WorkAppendixDirectory> list = workAppendixDirectoryService.list();//全部目录
List<WorkAppendixDirectory> fatherDirectoryList=new ArrayList<>();//存放所有父目录
List<WorkAppendixDirectory> childDirectoryList=new ArrayList<>();//存放所有子目录
// for循环将所有目录区分未父和子目录。保存到对用list
for (WorkAppendixDirectory dir:list){
if (dir.getParent()==null){
fatherDirectoryList.add(dir);
}else {
childDirectoryList.add(dir);
}
}
//将父和子对应的workAppendixDirectory转化为TreeData,并用list保存
List fatherDirTreeDataList = AppendixDirTreeData.TreeData.convertedAppendixDirToFatherTree(fatherDirectoryList);
List childDirTreeDataList= AppendixDirTreeData.TreeData.convertedAppendixDirToChildTree(childDirectoryList);
//根据父和子的TreeDataList,递归查询出每个父节点下的子节点
List dataTree = AppendixDirTreeData.TreeData.getTree(childDirTreeDataList, fatherDirTreeDataList);
System.out.println(dataTree);
return R.data(dataTree);
}
这样返回dataTree就OK啦。
我们可以看一下返回的结果:
我们可以看到,返回的data中有序号为0、1、2三个结果,分别为最大级别的父目录 “目录1 目录2 目录3”
点开目录1的children 会发现有索引0号一条数据 为目录5
点开目录5的children 会发现有索引0号一条数据 为目录7
由此可得,目录结构和我们设想的一样,
目录1{
......数据
children【
目录5{
.......数据
children【
目录7{
......数据
children:空
}
】
}
】
}
是不是和我们预先设想的一样呢?