Java集合转树结构(treeList)

java list集合转树结构(treeList)

复制代码
    我们在实际开发中,肯定会用到树结构,如部门树、菜单树等等。Java后端利用递归思路进行构建树形结构数据,返回给前端,能以下拉菜单等形式进行展示。今天,咱们就来说说怎么样将List集合转换成TreeList。

一、简介

树是n(n>=0)个结点的有限集。当n = 0时,称为空树。在任意一棵非空树中应满足:

有且仅有一个特定的称为根的结点。

当n>1时,其余节点可分为m(m>0)个互不相交的有限集T1,T2,...,Tm,其中每个集合本身又是一棵树,并且称为根的子树。

显然,树的定义是递归的,即在树的定义中又用到了自身,树是一种递归的数据结构。树作为一种逻辑结构,同时也是一种分层结构,具有以下两个特点:

复制代码
    树的根结点没有前驱,除根结点外的所有结点有且只有一个前驱。树中所有结点可以有零个或多个后继。因此n个结点的树中有n-1条边。

二、代码实现

1.jar依赖

复制代码
    为了简化代码,引入Lombok的Jar包,可省略实体类set()、get()方法

org.projectlombok lombok 1.16.12 2.树节点数据类

java 复制代码
/**
 *  TreeNode 树节点 (定义每一个节点的信息,即每一个节点对应一条数据信息)
 */
@Data
public class TreeNode {
 
    /** 节点ID */
    private Integer id;
 
    /** 父节点ID:顶级节点为0 */
    private Integer parentId;
 
    /** 节点名称 */
    private String label;
 
    /** 子节点 */
    private List<TreeNode> children;
 
    public TreeNode(Integer id, Integer parentId, String label) {
        this.id = id;
        this.parentId = parentId;
        this.label = label;
    }
}

3.构建树形类

理解思路:

1、首先获取所有的根节点(顶级节点),即根节点的parentId = 0。

2、根据每一个根节点,与所有节点集合(数据)进行判断,当前节点是否为其下的子节点。

3、若是,则递归调用构建树形;若不是,则表明该节点不属于其下子节点。

4、应继续循环判断节点父子关系,直到所有节点与根节点判断完毕。

java 复制代码
/**
 *  BuildTree 构建树形结构
 */
public class TreeBuild {
    
    // 保存参与构建树形的所有数据(通常数据库查询结果)
    public List<TreeNode> nodeList = new ArrayList<>();
 
    /**
     *  构造方法
     *  @param nodeList 将数据集合赋值给nodeList,即所有数据作为所有节点。
     */
    public TreeBuild(List<TreeNode> nodeList){
        this.nodeList = nodeList;
    }
 
    /**
     *   获取需构建的所有根节点(顶级节点) "0"
     *   @return 所有根节点List集合
     */
    public List<TreeNode> getRootNode(){
        // 保存所有根节点(所有根节点的数据)
        List<TreeNode> rootNodeList = new ArrayList<>();
        // treeNode:查询出的每一条数据(节点)
        for (TreeNode treeNode : nodeList){
            // 判断当前节点是否为根节点,此处注意:若parentId类型是String,则要采用equals()方法判断。
            if (0 == treeNode.getParentId()) {
                // 是,添加
                rootNodeList.add(treeNode);
            }
        }
        return rootNodeList;
    }
复制代码
/**
 *  根据每一个顶级节点(根节点)进行构建树形结构
 *  @return  构建整棵树
 */
public List<TreeNode> buildTree(){
    // treeNodes:保存一个顶级节点所构建出来的完整树形
    List<TreeNode> treeNodes = new ArrayList<TreeNode>();
    // getRootNode():获取所有的根节点
    for (TreeNode treeRootNode : getRootNode()) {
        // 将顶级节点进行构建子树
        treeRootNode = buildChildTree(treeRootNode);
        // 完成一个顶级节点所构建的树形,增加进来
        treeNodes.add(treeRootNode);
    }
    return treeNodes;
}

/**
 *  递归-----构建子树形结构
 *  @param  pNode 根节点(顶级节点)
 *  @return 整棵树
 */
public TreeNode buildChildTree(TreeNode pNode){
    List<TreeNode> childTree = new ArrayList<TreeNode>();
    // nodeList:所有节点集合(所有数据)
    for (TreeNode treeNode : nodeList) {
        // 判断当前节点的父节点ID是否等于根节点的ID,即当前节点为其下的子节点
        if (treeNode.getParentId().equals(pNode.getId())) {
            // 再递归进行判断当前节点的情况,调用自身方法
            childTree.add(buildChildTree(treeNode));
        }
    }
    // for循环结束,即节点下没有任何节点,树形构建结束,设置树结果
    pNode.setChildren(childTree);
    return pNode;
}

}

三、测试案例

/**

  • TreeController 树控制层

  • 方式:传递所有数据集合作为参数,调用buildTree()构建树形。

    */

    @RestController

    @RequestMapping("/tree")

    public class TreeController {

    @GetMapping("/treeTest")

    public AjaxResult treeTest(){

    复制代码
    // 模拟测试数据(通常为数据库的查询结果)
    List<TreeNode> treeNodeList = new ArrayList<>();
    treeNodeList.add(new TreeNode(1,0,"顶级节点A"));
    treeNodeList.add(new TreeNode(2,0,"顶级节点B"));
    treeNodeList.add(new TreeNode(3,1,"父节点是A"));
    treeNodeList.add(new TreeNode(4,2,"父节点是B"));
    treeNodeList.add(new TreeNode(5,2,"父节点是B"));
    treeNodeList.add(new TreeNode(6,3,"父节点的ID是3"));
    
    // 创建树形结构(数据集合作为参数)
    TreeBuild treeBuild = new TreeBuild(treeNodeList);
    // 原查询结果转换树形结构
    treeNodeList = treeBuild.buildTree();
    // AjaxResult:个人封装返回的结果体
    return AjaxResult.success("测试数据",treeNodeList);

    }

    }

    最终的测试结果:(json)

java 复制代码
{
	"msg":" 测试数据",
	"code": 200,
	"data": [
  		  {
			"id": 1,
			"parentId": 0,
			"label":"顶级节点A",
			"children": [
   		 {
					"id": 3,
    				"parentId": 1,
					"label":" 父节点是A"
					"children": [
						"id": 6,
						"parentId": 3,
						"label":" 父节点的ID是3
					}
				]
			}
		]
	}, 
	{
		"id": 2,
		"parentId": 0,
		"labe1":" 顶级节点B",
		"children": [{
				"id": 4,
				"parentId": 2,
				"label":" 父节点是B"
			},
			{
				"id": 5,
				"parentId": 2,
				"label":" 父节点是B
			}
		]
	}
]
}
复制代码
    本文介绍的是通过Java代码,将list集合转为树形结构数据,如有不对可以或更好的方案,欢迎指出和讨论。
相关推荐
chinesegf11 小时前
图文并茂的笔记、便签是如何用py开发的
笔记·状态模式
云闲不收2 天前
GraphQL教程
后端·状态模式·graphql
e***98574 天前
SpringMVC的工作流程
状态模式
q***08744 天前
SpringMVC的工作流程
状态模式
g***78914 天前
SpringBoot中使用TraceId进行日志追踪
spring boot·后端·状态模式
shuxiaohua6 天前
使用HttpURLConnection调用SSE采坑记录
状态模式
崎岖Qiu6 天前
状态模式与策略模式的快速区分与应用
笔记·设计模式·状态模式·策略模式·开闭原则
Jonathan Star7 天前
前端需要做单元测试吗?哪些适合做?
前端·单元测试·状态模式
一水鉴天8 天前
整体设计 全面梳理复盘 之40 M3 统摄三层 AI 的动态运营社区(Homepage)设计
架构·transformer·状态模式·公共逻辑
前端玖耀里11 天前
Vue + Axios + Node.js(Express)如何实现无感刷新Token?
状态模式