java构建树形结构的数据(省市区/多级菜单等)

829 阅读1分钟

1.写一个普通树节点的抽象类



import com.fasterxml.jackson.annotation.JsonBackReference;
import lombok.Data;

import java.util.List;
@Data
public abstract class Node<T extends Node> {

    /**
     * 节点id
     */
    private String nodeId;

    /**
     * 节点名称
     */
    private String nodeName;

    /**
     * 父级节点id
     */
    private String parentId;

    /**
     * 父级节点
     */
    private T parent;

    /**
     * 子节点
     */
    private List<T> children;

    /**
     * 通用节点赋值
     */
    public Node(String id, String name){
        this.nodeId = id;
        this.nodeName = name;
    }

    /**
     * 添加子节点
     */
    final void addChild(T node){
        this.children.add(node);
    }

    /**
     * 设置父节点
     */
    @JsonBackReference
    final void setParent(T node){
        this.parent = node;
    }

}

2.普通类继承抽象的树节点类

import lombok.Data;

@Data
public class MenuNode extends AbstractNode<MenuNode> {

    /**
     * 菜单id
     */
    private String menuId;

    /**
     * 菜单名称
     */
    private String menuName;

    /**
     * 菜单权限
     */
    private String author;

    /**
     * 通用节点赋值
     *
     * @param menuEntity
     */
    public MenuNode(MenuEntity menuEntity) {
        super(menuEntity.getMenuId(), menuEntity.getMenuName());
        this.author = menuEntity.getAuthor();
    }

3.树的抽象类


import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class AbstractTree<T extends AbstractNode> {

    private final Integer DEFAULT_INITIAL_CAPACITY = 1 << 4;

    /**
     * 存放菜单id和对应菜单的map
     */
    private Map<String, T> nodeMap;

    /**
     * 树的根
     */
    private List<T> roots;

    /**
     * 构造方法
     * @param abstractNodeList
     */
    AbstractTree(List<T> abstractNodeList){
        nodeMap = new HashMap<>(DEFAULT_INITIAL_CAPACITY);
        roots = new ArrayList<>();
        abstractNodeList.forEach(item -> {
            nodeMap.put(item.getNodeId(), item);
        });

        buildTree();
    }

    /**
     * 构建树
     */
    private final void buildTree() {
        for(T node : nodeMap.values()){
            if(StringUtils.isBlank(node.getParentId())){
                roots.add(node);
            }
            T parent = nodeMap.get(node.getParentId());
            if(parent != null){
                node.setParent(parent);
                parent.addChild(node);
            }
        }
    }

}

4.最后成形的一颗树

import java.util.List;
public class MenuTree extends AbstractTree<AbstractNode> {

    /**
     * 构造方法
     *
     * @param abstractNodeList
     */
    MenuTree(List<AbstractNode> abstractNodeList) {
        super(abstractNodeList);
    }
}