本文目录导读:

构建Java树形结构通常用于表示层级关系数据,如组织架构、菜单、分类等,以下是几种常见且实用的构建方式:
基础节点定义
// 通用树节点
public class TreeNode {
private Long id;
private Long parentId;
private String name;
private List<TreeNode> children = new ArrayList<>();
// 构造方法
public TreeNode(Long id, Long parentId, String name) {
this.id = id;
this.parentId = parentId;
this.name = name;
}
// Getter/Setter...
}
核心构建方法
import java.util.*;
import java.util.stream.Collectors;
public class TreeBuilder {
/**
* 构建树形结构(递归方式)
*/
public static List<TreeNode> buildTree(List<TreeNode> nodes) {
// 1. 获取所有根节点(parentId为null或0)
List<TreeNode> roots = nodes.stream()
.filter(node -> node.getParentId() == null || node.getParentId() == 0)
.collect(Collectors.toList());
// 2. 为每个根节点构建子节点
for (TreeNode root : roots) {
buildChildren(root, nodes);
}
return roots;
}
/**
* 递归构建子节点
*/
private static void buildChildren(TreeNode parent, List<TreeNode> nodes) {
List<TreeNode> children = nodes.stream()
.filter(node -> Objects.equals(node.getParentId(), parent.getId()))
.collect(Collectors.toList());
for (TreeNode child : children) {
buildChildren(child, nodes);
}
parent.setChildren(children);
}
/**
* 使用HashMap优化(推荐,性能更好)
*/
public static List<TreeNode> buildTreeFast(List<TreeNode> nodes) {
// 创建ID->Node的映射
Map<Long, TreeNode> nodeMap = new HashMap<>();
List<TreeNode> roots = new ArrayList<>();
// 将所有节点放入Map
for (TreeNode node : nodes) {
nodeMap.put(node.getId(), node);
}
// 构建父子关系
for (TreeNode node : nodes) {
if (node.getParentId() != null && node.getParentId() != 0) {
TreeNode parent = nodeMap.get(node.getParentId());
if (parent != null) {
parent.getChildren().add(node);
}
} else {
roots.add(node);
}
}
return roots;
}
}
实际应用示例
public class TreeDemo {
public static void main(String[] args) {
// 模拟数据库查询到的扁平数据
List<TreeNode> flatData = Arrays.asList(
new TreeNode(1L, 0L, "根节点"),
new TreeNode(2L, 1L, "节点A"),
new TreeNode(3L, 1L, "节点B"),
new TreeNode(4L, 2L, "节点A-1"),
new TreeNode(5L, 2L, "节点A-2"),
new TreeNode(6L, 3L, "节点B-1")
);
// 构建树
List<TreeNode> tree = TreeBuilder.buildTreeFast(flatData);
// 打印树(JSON格式)
System.out.println(new Gson().toJson(tree));
}
}
增强版节点(支持更多功能)
public class EnhancedTreeNode {
private Long id;
private Long parentId;
private String name;
private Boolean disabled; // 是否禁用
private Boolean checked; // 是否选中(用于树形选择框)
private Integer sort; // 排序字段
private List<EnhancedTreeNode> children = new ArrayList<>();
private Map<String, Object> extra = new HashMap<>(); // 扩展属性
// 添加辅助方法
public void addChild(EnhancedTreeNode child) {
this.children.add(child);
}
public boolean isLeaf() {
return children == null || children.isEmpty();
}
// Getter/Setter...
}
完整工具类
public class TreeUtil {
/**
* 通用树构建方法(支持泛型)
*/
public static <T extends TreeNode> List<T> buildTree(
List<T> nodes,
Function<T, Long> getId,
Function<T, Long> getParentId,
Function<T, List<T>> getChildren,
BiConsumer<T, List<T>> setChildren) {
Map<Long, T> nodeMap = nodes.stream()
.collect(Collectors.toMap(getId, node -> node));
List<T> roots = new ArrayList<>();
for (T node : nodes) {
Long parentId = getParentId.apply(node);
if (parentId == null || parentId == 0) {
roots.add(node);
} else {
T parent = nodeMap.get(parentId);
if (parent != null) {
List<T> children = getChildren.apply(parent);
if (children == null) {
children = new ArrayList<>();
setChildren.accept(parent, children);
}
children.add(node);
}
}
}
return roots;
}
}
Spring Boot项目中的使用
@Service
public class MenuServiceImpl implements MenuService {
@Autowired
private MenuMapper menuMapper;
@Override
public List<MenuVO> getMenuTree() {
// 从数据库查询所有菜单
List<Menu> menus = menuMapper.selectList(null);
// 转换为树节点
List<TreeNode> nodes = menus.stream()
.map(menu -> new TreeNode(menu.getId(), menu.getParentId(), menu.getName()))
.collect(Collectors.toList());
// 构建树
return TreeBuilder.buildTreeFast(nodes);
}
}
- 数据结构:节点需要包含
id、parentId和children列表 - 构建方式:
- 递归方式:逻辑清晰,但大数据量时性能较差
- HashMap方式:性能更好,推荐使用
- 空值处理:根节点的
parentId通常为null或0 - 排序支持:可以在构建后按
sort字段排序 - 扩展性:节点可以包含自定义属性和方法
选择哪种方式取决于你的具体需求,对于大多数业务场景,使用HashMap优化的方式就足够了。