添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

树形结构数据是后台开发中非常常见的一种数据结构。后台管理系统中必要的一种结构,常见的树形结构数据有,部门树,权限树等等,利用该数据结构可以让你的系统数据展示一目了然,并且为分配这些数据也提供了极大地便利。如图所示的是菜单树。
在这里插入图片描述
菜单选择树:
在这里插入图片描述

这样的树通常看起来容易实现,但是实际生成有一定的难度,尤其是没有顶级节点时(一共n个节点,其中n-1个节点直接或者间接挂在一个节点上的情况),代码稍稍有点复杂。生成这样的一棵树,必须满足节点有id(节点唯一标识符),pid(父节点的唯一标识符)和子节点集合。用java类可以描述为:

@Data
public class TreeNode {
     * 唯一标识符
    private Long key;
     * 节点描述
    private String title;
     * 父节点唯一标识符
    private Long parentId;
     * 子节点集合
    private List<TreeNode> children;

注意: 其中的@Data是Lombok提供的注解,提供了字段的get、set、equals、hashCode、canEqual、toString等方法的生成。如果不了解的同学,自行百度。

如果不漏掉所有的节点,需要先找出所有的父节点

public class Tree {
    List<TreeNode> nodes;
    public Tree(List<TreeNode> nodes) {
        this.nodes = nodes;
     * 构建树形结构
    public List<TreeNode> buildTree() {
        List<TreeNode> treeNodes = new ArrayList<>();
        List<TreeNode> rootNodes = getRootNodes();
        for (TreeNode rootNode : rootNodes) {
            buildChildNodes(rootNode);
            treeNodes.add(rootNode);
        return treeNodes;
     * 递归子节点
    private void buildChildNodes(TreeNode node) {
        List<TreeNode> children = getChildNodes(node);
        if (!children.isEmpty()) {
            for (TreeNode child : children) {
                buildChildNodes(child);
            node.setChildren(children);
     * 获取父节点下所有的子节点
    public List<TreeNode> getChildNodes(TreeNode pNode) {
        List<TreeNode> childNodes = new ArrayList<>();
        for (TreeNode n : nodes) {
            if (pNode.getKey().equals(n.getParentId())) {
                childNodes.add(n);
        return childNodes;
     * 判断是否为根节点
    public boolean rootNode(TreeNode node) {
        boolean isRootNode = true;
        for (TreeNode n : nodes) {
            if (node.getParentId().equals(n.getKey())) {
                isRootNode = false;
                break;
        return isRootNode;
     * 获取集合中所有的根节点
    public List<TreeNode> getRootNodes() {
        List<TreeNode> rootNodes = new ArrayList<>();
        for (TreeNode n : nodes) {
            if (rootNode(n)) {
                rootNodes.add(n);
        return rootNodes;

从上面代码中可以看到,主要有两个重要的步骤,一、获取集合中的所有的根节点;二、递归子节点。

不难看出该类只有一个构造器,并且构造的时候需要传入节点集合。

public class Test {
    public static void main(String[] args) {
        // 构造节点集合,通常是数据库中查出
        List<TreeNode> list = new ArrayList<>();
        Tree tree = new Tree(list);
        List<TreeNode> treeNodes = tree.buildTree();

通常这个生成之后,数据就可以交由前端去渲染。可供常见的前端框架antd,iview等使用,具体情况具体修改。生成已经有了,但是如果只有子节点,如果完整渲染出仅包含该子节点的树呢?其实思路也是和这个类似的

Hutool是一个小而全的 Java 工具类库,通过静态方法封装,降低相关 API 的学习成本,提高工作效率,使 Java 拥有函数式语言般的优雅。 构建菜单树是我们常用的功能,构建树的时候就考虑,能不能写一个公共的类,用来构建树,思索了许久,没... 递归实现树结构数据 一、递归概念:自己的理解,自己调用自己,何为自己钓鱼呢自己,比如 下面的**chilMenus.add(buildChilTree(menuNode))**就是在自己调用自己,查询到下一级的下一级,有几级我就调用几次我自己,从而实现树状结构中的父节点下的所有子级。 //递归,建立子树形结构 public Menu buildChilTree(Menu pNode){ List<Menu> chilMenus =new ArrayList<Menu>(); 2.造一些数据 注意:根节点的pid=0,其他节点的pid跟id是有对应的父子关系的。这里只展示递归生成树的代码,查询数据库的操作非常简单,只用到了一句sql,然后将结果封装成List。 service代码: 返回数据格式如下:... @TableName("流域单元") @ApiModel(value = "流域单元", description = "流域单元") public class WaterCode implements Serializable { @TableField(value = "PID") @ApiModelProperty(va // 构建node列表(数据源) List<TreeNode<String>> nodeList = CollUtil.newArrayList(); nodeList.add(new TreeNode<>("1", "0", "系统管理", 5)); nodeList.add(new TreeNode<..