简介
在实际项目开发中,例如构造菜单或组织架构的数据时,经常会需要返回树状的层级数据。解决这个问题可以通过构造 SQL 语句或者递归来进行构造。本文推荐使用递归方式来构建树状数据。
数据模型
假设数据表使用 parentId
字段进行父子级关联。定义一个 VO 类来表示树节点:
java
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(description = "TreeVO")
public class TreeVO {
@ApiModelProperty(value = "主键id")
private long id;
@ApiModelProperty(value = "父id")
private long parentId;
@ApiModelProperty(value = "子节点")
private List<TreeVO> children = new ArrayList<>();
}
工具类
构建树节点
通过递归方法构建树状结构:
java
import java.util.*;
public class TreeUtil {
/**
* 根据 pid 构建树节点
*/
public static <T extends TreeVO> List<T> build(List<T> treeNodes, Integer pid) {
List<T> treeList = new ArrayList<>();
for (T treeNode : treeNodes) {
if (pid.equals(treeNode.getParentId())) {
treeList.add(findChildren(treeNodes, treeNode));
}
}
return treeList;
}
/**
* 查找子节点
*/
private static <T extends TreeVO> T findChildren(List<T> treeNodes, T rootNode) {
for (T treeNode : treeNodes) {
if (rootNode.getId().equals(treeNode.getParentId())) {
rootNode.getChildren().add(findChildren(treeNodes, treeNode));
}
}
return rootNode;
}
/**
* 构建树节点(无参版本)
*/
public static <T extends TreeVO> List<T> build(List<T> treeNodes) {
List<T> result = new ArrayList<>();
// list 转 map
Map<Long, T> nodeMap = new LinkedHashMap<>(treeNodes.size());
for (T treeNode : treeNodes) {
nodeMap.put(treeNode.getId(), treeNode);
}
for (T node : nodeMap.values()) {
T parent = nodeMap.get(node.getParentId());
if (parent != null && !node.getId().equals(parent.getId())) {
parent.getChildren().add(node);
continue;
}
result.add(node);
}
return result;
}
}
使用示例
假设你有一个包含多个 TreeVO
对象的列表 treeNodes
,你可以通过以下方式构建树状结构:
java
List<TreeVO> treeNodes = // 获取你的数据列表
List<TreeVO> tree = TreeUtil.build(treeNodes, 0); // 假设根节点的 parentId 为 0