在Java中实现树结构并将其存储在MySQL数据库
在Java中实现树结构并将其存储在MySQL数据库中涉及几个步骤。
MySQL表设计
CREATE TABLE TreeNode (
id INT AUTO_INCREMENT PRIMARY KEY,
parentId INT,
name VARCHAR(255)
)
id 是节点的唯一标识符。
parentId 是父节点的ID,根节点的 parentId 为 NULL。
name 是节点的名称或其他属性。
树节点
@Data
public class TreeNode {
private int id;
private Integer parentId;
private String name;
private List<TreeNode> children;
}
代码逻辑实现
递归实现
public class TreeBuilder {
// 使用Map来存储节点,方便根据id查找
private static Map<Integer, TreeNode> nodeMap = new HashMap<>();
// 递归构建树的方法
public static TreeNode buildTree(List<TreeNode> nodes, Integer rootPid) {
// 将所有节点添加到Map中,方便后续查找
for (TreeNode node : nodes) {
nodeMap.put(node.getId(), node);
}
// 从Map中根据rootPid找到根节点,并递归构建树
return buildTreeFromMap(rootPid);
}
// 递归辅助方法,从Map中构建树
private static TreeNode buildTreeFromMap(Integer pid) {
TreeNode currentNode = null;
if (pid == null) {
currentNode = nodeMap.get(pid);
}
// 如果pid为null,则查找父ID为null的节点作为根节点(假设只有一个根节点)
if (currentNode == null && pid == null) {
for (TreeNode node : nodeMap.values()) {
if (node.getPid() == null) { // 或者使用 node.getPid() == SomeSpecialValue
currentNode = node;
break; // 找到根节点后退出循环
}
}
}
// 如果找到了当前节点(无论是根节点还是其他节点),则递归地为其添加子节点
if (currentNode != null) {
for (TreeNode node : nodeMap.values()) {
if (Objects.equals(node.getPid(), currentNode.getId())) {
currentNode.getChildren().add(buildTreeFromMap(node.getId()));
}
}
}
return currentNode;
}
}
非递归实现
public class TreeBuilder {
public static TreeNode buildTree(List<TreeNode> nodes) {
// 使用Map来存储节点,方便根据id查找
Map<Integer, TreeNode> nodeMap = new HashMap<>();
TreeNode root = null;
// 第一步:将所有节点添加到Map中
for (TreeNode node : nodes) {
nodeMap.put(node.getId(), node);
}
// 第二步:构建树结构
for (TreeNode node : nodes) {
// 如果pid为null,说明是根节点
if (node.getPid() == null) {
// 对多个根结点的检查
if (root != null) {
throw new IllegalArgumentException("结点列表中包含多个根结点");
}
root = node;
} else {
// 根据pid找到父节点,并将当前节点添加到父节点的children列表中
TreeNode parentNode = nodeMap.get(node.getPid());
if (parentNode != null) {
parentNode.getChildren().add(node);
}
}
}
return root;
}
}
测试
// 测试方法
public static void main(String[] args) {
List<TreeNode> nodes = new ArrayList<>();
nodes.add(new TreeNode(1, null, "Root")); // 根节点,pid为null
nodes.add(new TreeNode(2, 1, "Child1"));
nodes.add(new TreeNode(3, 1, "Child2"));
nodes.add(new TreeNode(4, 2, "Grandchild1"));
nodes.add(new TreeNode(5, 2, "Grandchild2"));
nodes.add(new TreeNode(6, 3, "Grandchild3"));
// 构建树
TreeNode tree = buildTree(nodes, null);
// 打印树结构
System.out.println(JSONObject.toJSONString(tree));
}
输出结果:
{
"children": [
{
"children": [
{
"children": [
],
"id": 6,
"name": "Grandchild3",
"pid": 3
}
],
"id": 3,
"name": "Child2",
"pid": 1
},
{
"children": [
{
"children": [
],
"id": 4,
"name": "Grandchild1",
"pid": 2
},
{
"children": [
],
"id": 5,
"name": "Grandchild2",
"pid": 2
}
],
"id": 2,
"name": "Child1",
"pid": 1
}
],
"id": 1,
"name": "Root"
}
多个根节点的树生成逻辑
基本思路:
1.创建一个HashMap来存储所有节点,以便我们可以根据ID快速查找它们。
2.我们遍历节点列表,对于每个节点,我们检查其pid。如果pid为null,我们将该节点添加到根节点列表中。否则,我们查找其父节点,并将当前节点添加到父节点的子节点列表中。
3.我们返回根节点列表,它可能包含多个根节点。
public static List<TreeNode> buildTree(List<TreeNode> nodes) {
Map<Integer, 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.getPid() == null) {
// 如果pid为null,说明是根节点
roots.add(node);
} else {
// 根据pid找到父节点,并将当前节点添加到父节点的children列表中
TreeNode parentNode = nodeMap.get(node.getPid());
if (parentNode != null) {
parentNode.getChildren().add(node);
}
}
}
return roots; // 返回根节点列表,可能包含多个根节点
}
测试
// 测试方法
public static void main(String[] args) {
List<TreeNode> nodes = new ArrayList<>();
// 创建根节点
TreeNode root1 = new TreeNode();
root1.setId(1);
root1.setPid(null);
root1.setName("Root 1");
nodes.add(root1);
TreeNode root2 = new TreeNode();
root2.setId(2);
root2.setPid(null);
root2.setName("Root 2");
nodes.add(root2);
// 创建子节点
TreeNode child1 = new TreeNode();
child1.setId(3);
child1.setPid(1); // child1 是 root1 的子节点
child1.setName("Child 1 of Root 1");
nodes.add(child1);
TreeNode child2 = new TreeNode();
child2.setId(4);
child2.setPid(1); // child2 也是 root1 的子节点
child2.setName("Child 2 of Root 1");
nodes.add(child2);
TreeNode child3 = new TreeNode();
child3.setId(5);
child3.setPid(2); // child3 是 root2 的子节点
child3.setName("Child 1 of Root 2");
nodes.add(child3);
// 创建三级节点
TreeNode grandChild1 = new TreeNode();
grandChild1.setId(6);
grandChild1.setPid(3); // grandChild1 是 child1 的子节点
grandChild1.setName("Grandchild 1 of Child 1 of Root 1");
nodes.add(grandChild1);
TreeNode grandChild2 = new TreeNode();
grandChild2.setId(7);
grandChild2.setPid(4); // grandChild2 是 child2 的子节点
grandChild2.setName("Grandchild 1 of Child 2 of Root 1");
nodes.add(grandChild2);
List<TreeNode> tree = buildTree(nodes);
// 打印树结构(这里只是简单地打印每个节点的名称和它的子节点)
printTree(tree, 0); // 0 是缩进级别
}
// 辅助方法,用于打印树结构
private static void printTree(List<TreeNode> nodes, int level) {
for (TreeNode node : nodes) {
for (int i = 0; i < level; i++) {
System.out.print(" "); // 缩进
}
System.out.println(node.getName());
printTree(node.getChildren(), level + 1); // 递归打印子节点
}
}
输出结果:
[
{
"children": [
{
"children": [
{
"children": [
],
"id": 6,
"name": "Grandchild 1 of Child 1 of Root 1",
"pid": 3
}
],
"id": 3,
"name": "Child 1 of Root 1",
"pid": 1
},
{
"children": [
{
"children": [
],
"id": 7,
"name": "Grandchild 1 of Child 2 of Root 1",
"pid": 4
}
],
"id": 4,
"name": "Child 2 of Root 1",
"pid": 1
}
],
"id": 1,
"name": "Root 1"
},
{
"children": [
{
"children": [
],
"id": 5,
"name": "Child 1 of Root 2",
"pid": 2
}
],
"id": 2,
"name": "Root 2"
}
]
原文地址:https://blog.csdn.net/weixin_43833540/article/details/143475920
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!