我这里需要的数据格式这这样的:

java三级 Java三级树新增_java三级

数据库的部分数据如下:

java三级 Java三级树新增_子节点_02

直接上代码,首先创建一个bean类,进行封装数据,(可以直接用Map,但用来比较费劲,我还是采用将数据库中的数据封装到bean 中,更直接些)

public class UnCdeAreaBean implements Serializable {

	private static final long serialVersionUID =  8139867807928157021L;

	/**
	 * 主键6位串
	 */
	private String value; // 这里是数据库中id ,因实际json显示需要改为value

	/**
	 * 名称
	 */
	private String text; // 这里是数据库中name,因实际json显示需要改为text

	/**
	 * 父节点ID
	 */
	private String pid;

	/**
	 * 级别
	 */
	private String numLevel;

	/**
	 * 是否有效  1:有效   0:无效
	 */
	private String isValid;


	private List<UnCdeAreaBean> children = new ArrayList<>();

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}


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

//	public String getName() {
//		return this.name;
//	}
//
//	public void setName(String name) {
//		this.name = name;
//	}


	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public String getPid() {
		return this.pid;
	}

	public void setPid(String pid) {
		this.pid = pid;
	}

	public String getNumLevel() {
		return this.numLevel;
	}

	public void setNumLevel(String numLevel) {
		this.numLevel = numLevel;
	}


	public String getIsValid() {
		return this.isValid;
	}

	public void setIsValid(String isValid) {
		this.isValid = isValid;
	}


//	public List<UnCdeAreaBean> getNodes() {
//		return nodes;
//	}
//
//	public void setNodes(List<UnCdeAreaBean> nodes) {
//		this.nodes = nodes;
//	}


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

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

	public UnCdeAreaBean(String value, String text, String pid, String numLevel) {
		this.value = value;
		this.text = text;
		this.pid = pid;
		this.numLevel = numLevel;
	}

	public UnCdeAreaBean(){}
}

接下来就是从数据库中获取数据,然后进行封装到上面创建的实体中:

public List<UnCdeAreaBean> getAreaInfoOptimize() {
        // 从数据库中获取地区数据
        String sql = " select t.* from xxx_tab t WHERE t.is_valid = '1' AND t.num_level < 4 ORDER BY t.id  ";
        List<Map<String, Object>> unCdeAreas = this.findForJdbc(sql);

        // 将List<Map<String, Object>> 转成  List<UnCdeAreaBean>
        List<UnCdeAreaBean> UnCdeAreaBeanArrayList = new ArrayList<>();
        unCdeAreas.forEach(map -> {
            UnCdeAreaBean UnCdeAreaBean = new UnCdeAreaBean((String) map.get("ID"),(String) map.get("NAME"),
                    map.get("PID").toString(), String.valueOf(map.get("NUM_LEVEL")));
            UnCdeAreaBeanArrayList.add(UnCdeAreaBean);
        });

        // 创建一个顶层节点
        UnCdeAreaBean root = new UnCdeAreaBean();
        // 构建树结构
        UnCdeAreaBean areaBean = buildNodes(root, UnCdeAreaBeanArrayList);
//        System.out.println("JSON.toJSONString(root) = " +JSON.toJSONString(areaBean));

        List<UnCdeAreaBean> nodes = areaBean.getChildren();
//       System.out.println("List<UnCdeAreaBean> nodes "+JSONArray.toJSONString(nodes));
        
        return nodes;
    }

构建树的代码:

public static UnCdeAreaBean buildNodes(UnCdeAreaBean root, List<UnCdeAreaBean> nodes) {

        // 剩余节点(还没有找到父节点的节点)
        ArrayList<UnCdeAreaBean> remainNodes = new ArrayList<>();
        // 当前节点下的子节点
        ArrayList<UnCdeAreaBean> child = new ArrayList<>();

        Iterator<UnCdeAreaBean> iterator = nodes.iterator();
        while (iterator.hasNext()) {
            UnCdeAreaBean node = iterator.next();
            // 顶层节点 为多个的时候 北京市、天津市、河北省...就是第一层的时候
            if (Objects.equals(node.getNumLevel(), "1")) {
//                root = node;
                child.add(node); // 这里解释一下,我先将北京市、天津市、河北省...添加child 中作为第一层节点。实际中可能还会遇到这种情况:一个超级root顶节点,只是用来展开,没有实际含义的,点击就展开,root下面才是北京市、天津市、河北省... 这种情况就直接放开注释 root = node ,将child.add(node) 注释即可

                continue;
            }
            // 该节点找到了子节点
            if (Objects.equals(root.getValue(), node.getPid())) {
                child.add(node);
            } else {
                // 没有找到子节点
                remainNodes.add(node);
            }
        }
        // 根节点设置子节点
        root.setChildren(child);
        // 每一个节点再去寻找对应的子节点
        root.getChildren().stream().forEach(x -> {
            buildNodes(x, remainNodes);
        });
        return root;
    }

 

PS: 这里我遇到的一个问题,就是实际需要构建的树结构,有多个顶节点,如:北京市、天津市、河北省 等,而 有一个顶节点的,如:中国下面北京市、天津市、河北省,这里省上层还有一个root顶节点中国。不知道有没有说清楚。

数据如下:

第一种情况,有一个顶节点的  xxx公司就是root顶节点      

        menus.add(new Menu("0", "xxx公司", "", "1"));
        menus.add(new Menu("1", "财务部", "0", "2"));
        menus.add(new Menu("2", "人事部", "0", "2"));
        menus.add(new Menu("11", "财务部11", "1", "3"));
        menus.add(new Menu("12", "财务部12", "1", "3"));
        menus.add(new Menu("22", "财务部22", "2", "3"));
        menus.add(new Menu("21", "财务部21", "2", "3"));

   
        第二种情况,多个顶节点的:财务部 和 人事部 并列的顶节点
//        menus.add(new Menu("0", "xxx公司", "", "1"));
        menus.add(new Menu("1", "财务部", "1", "2"));
        menus.add(new Menu("2", "人事部", "2", "2"));
        menus.add(new Menu("11", "财务部11", "1", "3"));
        menus.add(new Menu("12", "财务部12", "1", "3"));
        menus.add(new Menu("22", "财务部22", "2", "3"));
        menus.add(new Menu("21", "财务部21", "2", "3"));

上述举例的数据得到的json

第一种情况结果,有一个顶层节点  xxx公司,然后公司下面 才是 财务部和人事部

{
    "id":"0",
    "level":"1",
    "name":"xxx公司",
    "nodes":[
        {
            "id":"1",
            "level":"2",
            "name":"财务部",
            "nodes":[
                {
                    "id":"11",
                    "level":"3",
                    "name":"财务部11",
                    "nodes":[

                    ],
                    "parentId":"1"
                },
                {
                    "id":"12",
                    "level":"3",
                    "name":"财务部12",
                    "nodes":[

                    ],
                    "parentId":"1"
                }
            ],
            "parentId":"0"
        },
        {
            "id":"2",
            "level":"2",
            "name":"人事部",
            "nodes":[
                {
                    "id":"22",
                    "level":"3",
                    "name":"财务部22",
                    "nodes":[

                    ],
                    "parentId":"2"
                },
                {
                    "id":"21",
                    "level":"3",
                    "name":"财务部21",
                    "nodes":[

                    ],
                    "parentId":"2"
                }
            ],
            "parentId":"0"
        }
    ],
    "parentId":""
}

第二种情况json: 直接就是财务部和人事部 作为顶节点,没有超级root 节点 “xxx公司”

{
    "nodes":[
        {
            "id":"1",
            "level":"2",
            "name":"财务部",
            "nodes":[
                {
                    "id":"11",
                    "level":"3",
                    "name":"财务部11",
                    "nodes":[

                    ],
                    "parentId":"1"
                },
                {
                    "id":"12",
                    "level":"3",
                    "name":"财务部12",
                    "nodes":[

                    ],
                    "parentId":"1"
                }
            ],
            "parentId":"0"
        },
        {
            "id":"2",
            "level":"2",
            "name":"人事部",
            "nodes":[
                {
                    "id":"22",
                    "level":"3",
                    "name":"财务部22",
                    "nodes":[

                    ],
                    "parentId":"2"
                },
                {
                    "id":"21",
                    "level":"3",
                    "name":"财务部21",
                    "nodes":[

                    ],
                    "parentId":"2"
                }
            ],
            "parentId":"0"
        }
    ]
}

如有问题,欢迎交流指正。