首页 > 技术文章 > Java 处理树形结构数据

blackCatFish 2020-08-17 17:47 原文

在写项目中后台管理可能需要一些动态菜单树,所以在此记录一下先看下json数据格式

{
  "reason": "SUCCESS",
  "code": 200,
  "data": [
    {
      "id": "5",
      "labelName": "测试4",
      "parentId": null,
      "cheaked": "false",
      "children": [
        {
          "id": "6",
          "labelName": "标签测试",
          "parentId": "5",
          "cheaked": "false",
          "children": []
        },
        {
          "id": "11",
          "labelName": "二级",
          "parentId": "5",
          "cheaked": "false",
          "children": []
        }
      ]
    },
    {
      "id": "7",
      "labelName": "测试五级",
      "parentId": null,
      "cheaked": "false",
      "children": [
        {
          "id": "8",
          "labelName": "测试四级",
          "parentId": "7",
          "cheaked": "false",
          "children": [
            {
              "id": "9",
              "labelName": "测试三级",
              "parentId": "8",
              "cheaked": "false",
              "children": []
            }
          ]
        }
      ]
    },
    {
      "id": "10",
      "labelName": "一级",
      "parentId": null,
      "cheaked": "false",
      "children": []
    }
  ],
  "message": null
}

1.先分析一下:当一行数据parentId是空的 肯定是第一层菜单,若有一行parentId是这行的Id那么就是这行的孩子

实体类

package com.cmbchina.ccd.itpm.label.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author zly
 * @Date 2019/9/27 14:17
 */
@Entity
@Table(name = "asset_label")
public class Label implements Serializable{
    @Id
    private String id;
    private String labelName;
    private String parentId;
    private String cheaked;
    @Transient
    private List<Label> children = new ArrayList<>();

    public Label(String id, String labelName, String parentId, List<Label> children) {
        this.id = id;
        this.labelName = labelName;
        this.parentId = parentId;
        this.children = children;
    }

    public Label() {
    }
    public String getCheaked() {
        return cheaked;
    }

    public void setCheaked(String cheaked) {
        this.cheaked = cheaked;
    }

    @Override
    public String toString() {
        return "Label{" + "id='" + id + '\'' + ", labelName='" + labelName + '\'' + ", parentId='" + parentId + '\'' +
               ", cheaked='" + cheaked + '\'' + ", children=" + children + '}';
    }

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

    public void setChildren(List<Label> children) {
        this.children = children;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getLabelName() {
        return labelName;
    }

    public void setLabelName(String labelName) {
        this.labelName = labelName;
    }

    public String getParentId() {
        return parentId;
    }

    public void setParentId(String parentId) {
        this.parentId = parentId;
    }
}

建表语句

CREATE TABLE `asset_label` (
  `id` int(255) NOT NULL AUTO_INCREMENT COMMENT '菜单Id',
  `labelName` varchar(255) DEFAULT NULL COMMENT '菜单名称',
  `parentId` varchar(255) DEFAULT NULL COMMENT '父级ID',
  `cheaked` varchar(255) DEFAULT 'false' COMMENT '是否勾选',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

重点来了 逻辑代码处理

 public R getAll() {
        List<Label> labelList = labelDao.getLabelList();
        return R.ok(makeTreeLabelDto(labelList));
    }

    //构建菜单树
    public List<Label> makeTreeLabelDto(List<Label> labelList) {
        List<Label> firstLabelDto = new ArrayList<>();
        Map<String, Label> labelMap = new HashMap<>();
        for (Label label : labelList) {
            labelMap.put(label.getId(), label);
            //判断是否有父节点 (没有父节点本身就是个父菜单)
            if (label.getParentId() == null) {
                firstLabelDto.add(label);
            }
            //找出不是父级菜单的且集合中包括其父菜单ID
            if (label.getParentId() != null && labelMap.containsKey(label.getParentId())) {
                labelMap.get(label.getParentId()).getChildren().add(label);
            }
        }
        return firstLabelDto;
    }
 labelDao.getLabelList()这个方法就是将数据库所有数据查询出来没有贴出主要看构建树形结构的逻辑代码
这样就可以实现文章开头中的数据格式

推荐阅读