实体类
@Data
public class TreeData {
private static final long serialVersionUID = 1L;
/** 节点ID */
@Schema(description = "节点ID", example = "1")
private String id;
/** 父节点ID:顶级节点为0 */
@Schema(description = "父节点ID", example = "1")
private String parentId;
/** 节点名称 */
@Schema(description = "节点名称", example = "1")
private String name;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
/** 子节点 */
private List<TreeData> children;
public TreeData() {
}
//通过指定构造器函数可以快速的完成实体类转换
}
工具类
public class TreeUtils {
//-------------------以下是固定类转换树形结构------------------------------------
/**
* @Author: zhangsk
* @Description: 修改形成树工具类方法 ----同一改为使用改方法
* @DateTime: 14:24 2024/3/21
* @Params:
* @Return
*/
public static List<TreeData> buildDeptTree(Set<TreeData> depts) {
List<TreeData> returnList = new ArrayList<TreeData>();
List<String> tempList = new ArrayList<>();
for (TreeData dept : depts) {
tempList.add(dept.getId());
}
for (Iterator<TreeData> iterator = depts.iterator(); iterator.hasNext(); ) {
TreeData dept = (TreeData) iterator.next();
// 如果是顶级节点, 遍历该父节点的所有子节点
if (!tempList.contains(dept.getParentId())) {
recursionFn(depts, dept);
returnList.add(dept);
}
}
if (returnList.isEmpty()) {
returnList = depts.stream().collect(Collectors.toList());
}
return returnList;
}
/**
* 得到子节点列表
*/
private static List<TreeData> getChildList(Set<TreeData> list, TreeData t) {
List<TreeData> tlist = new ArrayList<TreeData>();
Iterator<TreeData> it = list.iterator();
while (it.hasNext()) {
TreeData n = (TreeData) it.next();
if (StringUtils.isNotEmpty(n.getParentId()) && n.getParentId().equals(t.getId())) {
tlist.add(n);
}
}
return tlist;
}
/**
* 递归列表
*/
private static void recursionFn(Set<TreeData> list, TreeData t) {
// 得到子节点列表
List<TreeData> childList = getChildList(list, t);
t.setChildren(childList);
for (TreeData tChild : childList) {
if (hasChild(list, tChild)) {
recursionFn(list, tChild);
} else {
// 没有子节点,设置children为空
tChild.setChildren(new ArrayList<>());
}
}
}
/**
* 判断是否有子节点
*/
private static boolean hasChild(Set<TreeData> list, TreeData t) {
return getChildList(list, t).size() > 0 ? true : false;
}
//------------------------------------------------------------------
// 部门顶级父级id
private static String PARENT_ID = "1";
// 保存参与构建树形的所有数据(通常数据库查询结果)
public Set<TreeData> nodeList = new HashSet<>();
/**
* 构造方法
* @param nodeList 将数据集合赋值给nodeList,即所有数据作为所有节点。
*/
public TreeUtils(Set<TreeData> nodeList){
this.nodeList = nodeList;
}
/**
* 对部门集合数据进行转换
* @param deptList
* @return
*/
public static Set<TreeData> exchangeToTree(List<DeptRespDTO> deptList){
if (CollectionUtils.isEmpty(deptList)) {
return null;
}
//集合数据进行对象转换
Set<TreeData> list = new HashSet<>();
for (DeptRespDTO fileDeptDO : deptList) {
TreeData tree = new TreeData(String.valueOf(fileDeptDO.getId()), String.valueOf(fileDeptDO.getParentId()), fileDeptDO.getName());
list.add(tree);
}
return list;
}
public static Set<TreeData> exchangeToTree01(List<DeptTreeRespDTO> deptList){
if (CollectionUtils.isEmpty(deptList)) {
return null;
}
//集合数据进行对象转换
Set<TreeData> list = new HashSet<>();
for (DeptTreeRespDTO fileDeptDO : deptList) {
TreeData tree = new TreeData(String.valueOf(fileDeptDO.getId()), String.valueOf(fileDeptDO.getParentId()), fileDeptDO.getName());
list.add(tree);
}
return list;
}
/**
* 根据每一个顶级节点(根节点)进行构建树形结构
* @return 构建整棵树
*/
public List<TreeData> buildTree(String id){
// treeNodes:保存一个顶级节点所构建出来的完整树形
List<TreeData> treeNodes = new ArrayList<TreeData>();
// getRootNode():获取所有的根节点
for (TreeData treeRootNode : getRootNode(id)) {
// 将顶级节点进行构建子树
treeRootNode = buildChildTree(treeRootNode);
// 完成一个顶级节点所构建的树形,增加进来
treeNodes.add(treeRootNode);
}
return treeNodes;
}
/**
* 获取需构建的所有根节点(顶级节点) "1"
* @return 所有根节点List集合
*/
public List<TreeData> getRootNode(String id) {
if (CollectionUtils.isEmpty(nodeList)) {
return null;
}
String pid = null;
if (id != null) {
pid = id;
} else {
pid = PARENT_ID;
}
List<TreeData> rootlist = new ArrayList<>();
for (TreeData treeData : nodeList) {
if (treeData != null && treeData.getParentId() != null && treeData.getParentId().equals(pid)) {
rootlist.add(treeData);
}
}
return rootlist;
}
/**
* 递归-----构建子树形结构
* @param treeRootNode 根节点(顶级节点)
* @return 整棵树
*/
private TreeData buildChildTree(TreeData treeRootNode) {
List<TreeData> childTree = new ArrayList<TreeData>();
// nodeList:所有节点集合(所有数据)
nodeList.stream()
// 判断当前节点的父节点ID是否等于根节点的ID,即当前节点为其下的子节点
.filter(treeNode->treeNode!=null && treeNode.getParentId() !=null && treeNode.getParentId().equals(treeRootNode.getId()))
// 再递归进行判断当前节点的情况,调用自身方法
.forEach(treeData ->childTree.add(buildChildTree(treeData)) );
// for循环结束,即节点下没有任何节点,树形构建结束,设置树结果
treeRootNode.setChildren(childTree);
return treeRootNode;
}
/**
* 递归获取某个父节点下面的所有子节点
*
* @param childFolderList 要返回的结果
* @param folderList 数据库查询出来的所有机构集合
* @param pid 父id
* TODO 注:本身的机构节点 不会 添加进去
*/
public static void getParentNode(List<InfoVO> childFolderList, List<InfoVO> folderList, String pid) {
folderList.stream()
//过滤出父id等于参数的id
.filter(folder -> folder != null && folder.getParentId() != null && folder.getParentId().equals(pid))
.forEach(childFolder -> {
//递归遍历下一级
getParentNode(childFolderList, folderList, childFolder.getFolderId());
//添加
childFolderList.add(childFolder);
});
}
/**
* 递归获取某个子节点的所有父节点
*
* @param parentMenu 要返回的结果
* @param menuList 数据库查询出来的所有机构集合
* @param folderId 节点id
* TODO 注:本身的机构节点 会 添加进去
*/
//文件夹递归获取父级
public static void getFolderParentByChild(List<InfoVO> parentMenu, List<InfoVO> menuList, String folderId) {
menuList.stream()
.filter(infoVO -> infoVO != null && folderId != null && infoVO.getFolderId().equals(folderId))
.forEach(folder -> {
getFolderParentByChild(parentMenu, menuList, folder.getParentId());
parentMenu.add(folder);
});
}
//部门递归获取父级
public static void getDeptParentByChild(List<DeptRespDTO> parentMenu, List<DeptRespDTO> menuList, Long deptId) {
menuList.stream()
.filter(infoVO -> infoVO != null && deptId != null && infoVO.getId().equals(deptId))
.forEach(dept -> {
getDeptParentByChild(parentMenu, menuList, dept.getParentId());
parentMenu.add(dept);
});
}
}