首页 归档 关于 learn love 工具

Java使用Nested set存储树形结构

sql修改

此文中,修改左右数值是使用sql实现,但是在初始化的时候,需要大量执行sql语句,短期间会造成数据库压力,所以现把数据读到内存中,然后计算左右数值,最后报存到数据库

代码

Node

package org.example.nestset;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Node {

    Integer id;
    Integer left;
    Integer right;
    List<Node> children = new ArrayList<>();
    Integer level;

    public Integer getLeft() {
        return left;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Node) {
            Node node = (Node) obj;
            return id.equals(node.id);
        }
        return false;

    }

    @Override
    public int hashCode() {
        return this.id;
    }

    public Integer getRight() {
        return right;
    }

    public List<Node> getChildren() {
        return children;
    }

    public Integer getLevel() {
        return level;
    }

 

    public Integer getId() {
        return id;
    }

  

    public void setLevel(Integer level) {
        this.level = level;
    }


    public void setLeft(Integer left) {
        this.left = left;
    }

    public void setRight(Integer right) {
        this.right = right;
    }

    public Node(Integer id) {
        this.id = id;
    }

    public String toString() {
        return String.join( "", Collections.nCopies(this.level -1, "  ")) + "|--" +  this.getId() + "(" + this.getLeft() + "," + this.getRight() + ")";

    }
}

Tree

package org.example.nestset;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Tree {

    Node root;

    /**
     * 用来设置节点right ,left
     */
    Integer seq = 0;

    public Tree() {
    }

    private final Map<Integer, Node> elementMap = new HashMap<>();


    /**
     * 初始化根节点
     */
    private void addRoot(Node root) {
        root.setLeft(1);
        root.setRight(2);
        root.setLevel(1); 
        this.root = root;
    }


    public void addChild(Node parent, Node child) {
        // 重复插入则忽略
        if (this.elementMap.containsKey(child.getId())) {
            return;
        }
        this.elementMap.put(child.getId(), child);
        if (parent == null) {
            addRoot(child);
            return;
        } 
        child.setLevel(parent.getLevel() + 1);
        parent.children.add(child);

    }


    private void search(List<Node> nodes) {
        for (Node node : nodes) {
            search(node);
        }
    }

    private void search(Node node) {
        node.setLeft(++seq);
        search(node.getChildren());
        node.setRight(++seq);
    }

    public void search() {
        search(root);
    }

    public void print() {
        System.out.println(root.toString());
        printChild(this.root, 1);

    }

    private void printChild(Node node, int i) {
        for (Node child : node.getChildren()) {
            System.out.println(child.toString());
            printChild(child, i + 2);
        }

    }

}

Test

package org.example.nestset;

import org.junit.Test;

public class NodeTest {


    @Test
    public void addChild() {

        Node node1 = new Node(1);

        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        Node node6 = new Node(6);
        Node node7 = new Node(7);
        Node node8 = new Node(8);
        Node node9 = new Node(9);
        Node node10 = new Node(10);
        Node node11 = new Node(11);
        Tree tree = new Tree();

        tree.addChild(null, node1);
        tree.addChild(node1, node2);
        tree.addChild(node1, node3);
        tree.addChild(node1, node4);

        tree.addChild(node2, node5);
        tree.addChild(node3, node6);
        tree.addChild(node4, node7);
        tree.addChild(node3, node8);
        tree.addChild(node4, node9);
        tree.addChild(node5, node10);

        tree.addChild(node1, node11);
        tree.search();
        tree.print();


    }
}

参考

https://www.werc.cz/blog/2015/07/19/nested-set-model-practical-examples-part-i