树形结构工具类TreeUtils
/**
* @Classname TreeUtils
* @Date 2021/11/1 下午4:25
* @Created by liuchao58
* @Description TODO
*/
public class TreeUtils {
/**
* 根据所有树节点列表,生成含有所有树形结构的列表
*
* @param nodes 树形节点列表
* @param <T> 节点类型
* @return 树形结构列表
*/
public static <T extends TreeNode<?>> List<T> generateTrees(List<T> nodes) {
List<T> roots = new ArrayList<>();
for (Iterator<T> ite = nodes.iterator(); ite.hasNext(); ) {
T node = ite.next();
if (node.root()) {
roots.add(node);
// 从所有节点列表中删除该节点,以免后续重复遍历该节点
ite.remove();
}
}
roots.forEach(r -> {
setChildren(r, nodes);
});
return roots;
}
/**
* 从所有节点列表中查找并设置parent的所有子节点
*
* @param parent 父节点
* @param nodes 所有树节点列表
*/
@SuppressWarnings("all")
public static <T extends TreeNode> void setChildren(T parent, List<T> nodes) {
List<T> children = new ArrayList<>();
Object parentId = parent.id();
for (Iterator<T> ite = nodes.iterator(); ite.hasNext(); ) {
T node = ite.next();
if (Objects.equals(node.parentId(), parentId)) {
children.add(node);
// 从所有节点列表中删除该节点,以免后续重复遍历该节点
ite.remove();
}
}
// 如果孩子为空,则直接返回,否则继续递归设置孩子的孩子
if (children.isEmpty()) {
return;
}
parent.setChildren(children);
children.forEach(m -> {
// 递归设置子节点
setChildren(m, nodes);
});
}
/**
* 获取指定树节点下的所有叶子节点
*
* @param parent 父节点
* @param <T> 实际节点类型
* @return 叶子节点
*/
public static <T extends TreeNode<?>> List<T> getLeafs(T parent) {
List<T> leafs = new ArrayList<>();
fillLeaf(parent, leafs);
return leafs;
}
/**
* 将parent的所有叶子节点填充至leafs列表中
*
* @param parent 父节点
* @param leafs 叶子节点列表
* @param <T> 实际节点类型
*/
@SuppressWarnings("all")
public static <T extends TreeNode> void fillLeaf(T parent, List<T> leafs) {
List<T> children = parent.getChildren();
// 如果节点没有子节点则说明为叶子节点
if (CollectionUtils.isEmpty(children)) {
leafs.add(parent);
return;
}
// 递归调用子节点,查找叶子节点
for (T child : children) {
fillLeaf(child, leafs);
}
}
}
标准树节点定义类TreeNode
/**
* @Classname TreeNode
* @Date 2021/11/1 下午4:25
* @Created by liuchao58
* @Description TODO
*/
public interface TreeNode<T> {
/**
* 获取节点id
*
* @return 树节点id
*/
T id();
/**
* 获取该节点的父节点id
*
* @return 父节点id
*/
T parentId();
/**
* 是否是根节点
*
* @return true:根节点
*/
boolean root();
/**
* 设置节点的子节点列表
*
* @param children 子节点
*/
void setChildren(List<? extends TreeNode<T>> children);
/**
* 获取所有子节点
*
* @return 子节点列表
*/
List<? extends TreeNode<T>> getChildren();
}
该树节点的实现类ResourceListDTO
/**
* @Classname ResourceListDTO
* @Date 2021/11/2 上午11:51
* @Created by liuchao58
* @Description TODO
*/
@Getter
@Setter
public class ResourceListDTO implements TreeNode<String> {
private String nodeId;
private String nodeParentId;
private String nodeName;
private List<ResourceListDTO> children;
@Override
public String id() {
return this.nodeId;
}
@Override
public String parentId() {
return this.nodeParentId;
}
@Override
public boolean root() {
return Objects.equals(this.nodeParentId, "0");
}
@Override
public void setChildren(List children) {
this.children = children;
}
}
使用:
通过某个方法获取List集合类型 的数据,调用TreeUtils.generateTrees 把根据pid,id上下级关系转成树形结构
List<ResourceListDTO> nodeDetailDTOList = getNodeDetailDTOList();
return TreeUtils.generateTrees(nodeDetailDTOList);