树形工具构建,java实现
package com.tansun.risk.rwa.common.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* 树形结构工具类
*
* @author IT_CREATE
* @date 2023/12/13 16:59
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class TreeBean<idType extends Comparable<idType>> implements Serializable {
private static final long serialVersionUID = 2978205537968679584L;
/*id和pid必须赋值,otherParameter装一些其他参数,比如name,key-value键值对的形式*/
/*将你从数据库查出来的集合循环,然后对每一行数据进行赋值转换成TreeBean结构,调用内部静态方法即可得到树形结构列表*/
/**
* id
*/
private idType id;
/**
* pid
*/
private idType pid;
/**
* 其他参数,需要展示的参数,比如name之类的
*/
private Map<String, Object> otherParameter;
/*---------------------------------下面这些不需要你赋值-------------------------------------------*/
/**
* 是否含有下一级
*/
private Boolean hasChildren;
/**
* 包含的子节点
*/
private List<TreeBean<idType>> children;
/**
* 子节点的集合大小
*/
private Long childrenSize;
/**
* 级别
*/
private Long level;
/**
* 使用递归方法建树(返回包含顶级节点)
*
* @param treeBeans 按规则转换的树形实体集合列表,没有层次结构
* @param topId 指定顶级节点id,必须指定
* @return 树形结构实体集合
*/
public static <idType extends Comparable<idType>> List<TreeBean<idType>> buildByRecursive(List<TreeBean<idType>> treeBeans, idType topId) {
return buildByRecursive(treeBeans, topId, true);
}
/**
* 使用递归方法建树
*
* @param treeBeans 按规则转换的树形实体集合列表,没有层次结构
* @param topId 指定顶级节点id,必须指定
* @param isCarryTopNode 返回节点层次结构,是否携带顶级节点返回
* <br/>设置为false,则将顶级节点的数据去除,返回指定顶级节点的子节点树形结构集合;
* <br/>设置为true,则返回包含顶级节点的树形结构集合(则返回集合中只包含一个顶级节点,顶级节点内部包含子节点信息)
* @return 树形结构实体集合
*/
public static <idType extends Comparable<idType>> List<TreeBean<idType>> buildByRecursive(List<TreeBean<idType>> treeBeans, idType topId, boolean isCarryTopNode) {
List<TreeBean<idType>> trees = new ArrayList<>();
TreeBean<idType> treeBeanTop = null;
// 循环节点集合,从顶级节点得二级节点开始层层递归
for (TreeBean<idType> treeBean : treeBeans) {
// 如果节点得父id是顶级节点,则进入查找子节点迭代,层层查找
// 如果父节点不是顶级节点,则忽略掉
if (treeBean.getPid().compareTo(topId) == 0) {
Long level = 1L;
// 如果需要将顶级节点返回,则除开顶级节点以下的节点则从2级开始表示,如果不反回顶级节点,则从1级开始表示
if (isCarryTopNode) {
level = 2L;
}
TreeBean<idType> treeBean2 = findChildren(treeBean, treeBeans, level);
if (CollectionUtils.isEmpty(treeBean2.getChildren())) {
treeBean2.setHasChildren(false);
treeBean2.setChildrenSize(0L);
treeBean2.setLevel(level);
} else {
treeBean2.setHasChildren(true);
treeBean2.setLevel(level);
treeBean2.setChildrenSize((long) treeBean2.getChildren().size());
}
trees.add(treeBean2);
} else if (isCarryTopNode && 0 == treeBean.getId().compareTo(topId)) {
// 记录集合中得顶级节点
treeBeanTop = treeBean;
}
}
if (!ObjectUtils.isEmpty(treeBeanTop)) {
treeBeanTop.setChildren(trees)
.setChildrenSize((long) trees.size())
.setHasChildren(true)
.setLevel(1L);
trees = new ArrayList<>();
trees.add(treeBeanTop);
}
return trees;
}
/**
* 递归查找子节点
*
* @param treeBean 当前节点
* @param treeBeans 所有节点
* @param level 当前节点的层次
* @return 树形结构实体
*/
private static <idType extends Comparable<idType>> TreeBean<idType> findChildren(TreeBean<idType> treeBean, List<TreeBean<idType>> treeBeans, Long level) {
for (TreeBean<idType> it : treeBeans) {
if (0 == treeBean.getId().compareTo(it.getPid())) {
if (treeBean.getChildren() == null) {
treeBean.setChildren(new ArrayList<>());
}
TreeBean<idType> treeBean2 = findChildren(it, treeBeans, level + 1);
if (!CollectionUtils.isEmpty(treeBean2.getChildren())) {
treeBean2.setHasChildren(true);
treeBean2.setChildrenSize((long) treeBean.getChildren().size());
treeBean2.setLevel(level + 1);
} else {
treeBean2.setHasChildren(false);
treeBean2.setChildrenSize(0L);
treeBean2.setLevel(level + 1);
}
treeBean.getChildren().add(treeBean2);
}
}
return treeBean;
}
/**
* 根据节点ID获取所有父节点
*
* @param treeBeans 构建好的树形结构(包含一个顶级节点的集合)
* @param id 节点Id
* @return 所有父节点(从最底层到最顶层顺序返回的集合,如果需要正序,请自行将集合进行反转即可)
*/
public static <idType extends Comparable<idType>> List<TreeBean<idType>> getAllParentNode(List<TreeBean<idType>> treeBeans, idType id) {
List<TreeBean<idType>> data = new ArrayList<>();
return allParentNodeIteration(data, treeBeans, id);
}
private static <idType extends Comparable<idType>> List<TreeBean<idType>> allParentNodeIteration(List<TreeBean<idType>> data, List<TreeBean<idType>> treeBeans, idType id) {
TreeBean<idType> it = getParentNode(treeBeans, id);
if (it != null) {
data.add(it);
return allParentNodeIteration(data, treeBeans, it.getPid());
}
return data;
}
/**
* 根据节点ID获取父节点
*
* @param treeBeans 构建好的树形结构(包含一个顶级节点的集合)
* @param id 节点Id
* @return 其父节点
*/
public static <idType extends Comparable<idType>> TreeBean<idType> getParentNode(List<TreeBean<idType>> treeBeans, idType id) {
TreeBean<idType> it = getNode(treeBeans, id);
if (it != null) {
return getNode(treeBeans, it.getPid());
} else {
return null;
}
}
/**
* 根据节点ID获取节点
*
* @param treeBeans 构建好的树形结构(包含一个顶级节点的集合)
* @param id 节点Id
* @return 节点
*/
public static <idType extends Comparable<idType>> TreeBean<idType> getNode(List<TreeBean<idType>> treeBeans, idType id) {
for (TreeBean<idType> treeBean : treeBeans) {
if (treeBean.getId().compareTo(id) == 0) {
return treeBean;
} else if (!CollectionUtils.isEmpty(treeBean.getChildren())) {
TreeBean<idType> node = getNode(treeBean.getChildren(), id);
if (node != null) {
return node;
}
}
}
return null;
}
/**
* 根据节点ID移出节点
*
* @param treeBeans 构建好的树形结构(包含一个顶级节点的集合)
* @param id 节点Id
*/
public static <idType extends Comparable<idType>> void removeNode(List<TreeBean<idType>> treeBeans, idType id) {
removeNode(null, treeBeans, id);
}
private static <idType extends Comparable<idType>> void removeNode(TreeBean<idType> parentNode, List<TreeBean<idType>> treeBeans, idType id) {
Iterator<TreeBean<idType>> iterator = treeBeans.iterator();
while (iterator.hasNext()) {
TreeBean<idType> next = iterator.next();
if (next.getId().compareTo(id) == 0) {
iterator.remove();
if (parentNode != null) {
parentNode.setHasChildren(!CollectionUtils.isEmpty(parentNode.getChildren()));
parentNode.setChildrenSize(CollectionUtils.isEmpty(parentNode.getChildren()) ? 0 : (long) parentNode.getChildren().size());
}
return;
} else if (!CollectionUtils.isEmpty(next.getChildren())) {
removeNode(next, next.getChildren(), id);
}
}
}
/**
* 根据节点ID更新节点参数Prams
*
* @param treeBeans 构建好的树形结构(包含一个顶级节点的集合)
* @param node 节点
*/
public static <idType extends Comparable<idType>> void updateNodeParams(List<TreeBean<idType>> treeBeans, TreeBean<idType> node) {
for (TreeBean<idType> treeBean : treeBeans) {
if (treeBean.getId().compareTo(node.getId()) == 0) {
treeBean.setOtherParameter(node.getOtherParameter());
return;
} else if (!CollectionUtils.isEmpty(treeBean.getChildren())) {
updateNodeParams(treeBean.getChildren(), node);
}
}
}
/**
* 根据节点替换相同ID的节点
*
* @param treeBeans 构建好的树形结构(包含一个顶级节点的集合)
* @param node 节点
*/
public static <idType extends Comparable<idType>> void replaceNode(List<TreeBean<idType>> treeBeans, TreeBean<idType> node) {
for (int i = 0; i < treeBeans.size(); i++) {
TreeBean<idType> treeBean = treeBeans.get(i);
if (treeBean.getId().compareTo(node.getId()) == 0) {
node.setLevel(treeBean.getLevel());
node.setHasChildren(!CollectionUtils.isEmpty(node.getChildren()));
node.setChildrenSize(CollectionUtils.isEmpty(node.getChildren()) ? 0 : (long) node.getChildren().size());
treeBeans.set(i, node);
return;
} else if (!CollectionUtils.isEmpty(treeBean.getChildren())) {
replaceNode(treeBean.getChildren(), node);
}
}
}
/**
* 添加节点,根据节点指定的pid添加到对应的父节点下
*
* @param treeBeans 构建好的树形结构(包含一个顶级节点的集合)
* @param node 节点
*/
public static <idType extends Comparable<idType>> void addNode(List<TreeBean<idType>> treeBeans, TreeBean<idType> node) {
for (TreeBean<idType> treeBean : treeBeans) {
if (treeBean.getId().compareTo(node.getPid()) == 0) {
if (treeBean.getChildren() == null) {
treeBean.setChildren(new ArrayList<>());
}
node.setLevel(treeBean.getLevel() + 1);
node.setHasChildren(!CollectionUtils.isEmpty(node.getChildren()));
node.setChildrenSize(CollectionUtils.isEmpty(node.getChildren()) ? 0 : (long) node.getChildren().size());
treeBean.getChildren().add(node);
treeBean.setHasChildren(true);
treeBean.setChildrenSize((long) treeBean.getChildren().size());
return;
} else if (!CollectionUtils.isEmpty(treeBean.getChildren())) {
addNode(treeBean.getChildren(), node);
}
}
}
/**
* 迭代树形结构,再每个节点上执行回调,回调会传入当前节点
*
* @param treeBeans 构建好的树形结构(包含一个顶级节点的集合)
* @param callback 回调函数 function(node){}
*/
public static <idType extends Comparable<idType>> void iteration(List<TreeBean<idType>> treeBeans, Action1<TreeBean<idType>> callback) {
for (TreeBean<idType> treeBean : treeBeans) {
if (callback != null) {
callback.call(treeBean);
}
if (!CollectionUtils.isEmpty(treeBean.getChildren())) {
iteration(treeBean.getChildren(), callback);
}
}
}
/**
* 接口
*
* @param <T> 泛型
*/
public interface Action1<T> {
/**
* 回调方法
*
* @param t 入参对象
* @throws RuntimeException 运行时异常
*/
void call(T t) throws RuntimeException;
}
}