Java递归构建树形结构

记录:在Java后台利用递归思路进行构建树形结构数据,返回给前端,能以下拉菜单等形式进行展示。

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

       <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.12</version></dependency>

一、树节点数据类

import lombok.Getter;
import lombok.Setter;import java.util.List;/***  TreeNode 树节点 (定义每一个节点的信息,即每一个节点对应一条数据信息)*/
@Setter
@Getter
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;}
}

二、构建树形类

理解思路(个人):

1、首先获取所有的根节点(顶级节点),即根节点的parentId = 0。
2、根据每一个根节点,与所有节点集合(数据)进行判断,当前节点是否为其下的子节点。
3、若是,则递归调用构建树形;若不是,则表明该节点不属于其下子节点。
4、应继续循环判断节点父子关系,直到所有节点与根节点判断完毕。

import java.util.ArrayList;
import java.util.List;/***  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;}}

三、测试案例

import com.lbf.common.core.domain.AjaxResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;
import java.util.List;/***  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);}
}

四、测试结果

img

五、总结

​ 本文介绍Java后台构建树形结构数据的设计思路及实现,在设计过程中,仍然存在许多未能充分理解的位置,若存在错误或更好实现方案,可分享/指出,共同学习进步。

Java返回树形结构的数据 (children方式)

以children这种方式的实体类来遍历子父级的树形结构。

//问题分类下拉表
@Override
public List<DA> selectDA(Long deptId,Long userId) {//根据deptId获取当前parentId  --- 第一步就是:获取根节点。DA current = sysDropDownListMapper.selectDA(deptId);//以下是可以拿到子部门内容DA root;//如果parentId为0,说明是根目录了。不是0就查找它的上级作为目录。if (current.getParentId()!=0){root = sysDropDownListMapper.selectDA(current.getParentId());}else {root = current;}//因为不需要返回parentId,所以返回同级就可以了。DA item = getItem(root);List<DA> list = item.getChildren();return list;
}/***  采用递归方式来获取树*/
private DA getItem(DA parentItem){//查询所有parentId为该数据的data --- 第二步:就是循环遍历parentId为该数据的 data。List<DA> items = sysDropDownListMapper.selectDAByParentId(parentItem.getDeptId());if (items!=null){parentItem.setChildren(items);for (DA item : items) {getItem(item);}}return parentItem;
}

对应实体类:

  • 通过children这种方式来给前端显示子父级关系。
package com.ruoyi.system.domain;import java.util.List;public class DA {Long deptId;String deptName;Long parentId;List<DA> children;public Long getParentId() {return parentId;}public void setParentId(Long parentId) {this.parentId = parentId;}public Long getDeptId() {return deptId;}public void setDeptId(Long deptId) {this.deptId = deptId;}public String getDeptName() {return deptName;}public void setDeptName(String deptName) {this.deptName = deptName;}public List<DA> getChildren() {return children;}public void setChildren(List<DA> children) {this.children = children;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554812.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP状态码含义:428、429、431、511431状态码详解

1、428 Precondition Required (要求先决条件) ​ 先决条件是客户端发送 HTTP 请求时&#xff0c;必须要满足的一些预设条件。一个好的例子就是 If-None-Match 头&#xff0c;经常用在 GET 请求中。如果指定了 If-None-Match &#xff0c;那么客户端只在响应中的 ETag 改变后才…

Java 异常——Exception详解

异常的介绍 异常的概念 异常 &#xff1a;指的是程序在执行过程中&#xff0c;出现的非正常的情况&#xff0c;最终会导致JVM的非正常停止。 在Java等面向对象的编程语言中&#xff0c;异常本身是一个类&#xff0c;产生异常就是创建异常对象并抛出了一个异常对象。Java处理…

Java中的URL类根据url获取网络文件快速入门Java中的URL(网络编程)

Java中的URL类 远程连接来实现应用。而且&#xff0c;这个平台现在已经可 以对国际互联网以及URL资源进行访问了。Java的URL类可以让访问网络资源就像是访问你本地的文件夹一样方便快捷。我们通过使用Java的URL类 就可以经由URL完成读取和修改数据的操作。 通过一个URL连接&a…

SpringMVC中Controller为什么能够处理并发访问?Springboot中的定时任务是否会发生阻塞?

文章目录SpringMVC中Controller为什么能够处理并发访问&#xff1f;当多个请求同时访问服务器的时候Controller、Service、DAO是线程安全的吗&#xff1f;关于类中的变量Controller、Service、DAO等类都默认为单例模式Controller、Service、DAO等类中的方法当中的并发问题关于D…

Java进阶 - 易错知识点整理

转载&#xff1a;https://blog.csdn.net/qq_33934427/article/details/125903960 文章目录1、JavaEE2、网络基础3、Mysql4、Spring/SpringMVC&#xff08;IOC装配、AOP增强、常用注解&#xff09;5、Spring Boot/Spring Cloud1&#xff09;SpringBoot部分2&#xff09;SpringCl…

MySQL 视图(详解) navicat如何创建视图

文章目录MySQL 视图&#xff08;详解一&#xff0c;视图概念使用视图的原因二&#xff0c;创建视图&#xff08;1&#xff09;基本语法&#xff08;2&#xff09;创建基于单表的视图【实例 1】【实例 2】&#xff08;3&#xff09;创建基于多表的视图【实例 3】&#xff08;4&a…

使用set集合去除重复元素@EqualsAndHashCode注解

如何使用set集合去重 ​ 我们都知道&#xff0c;set集合是无序的&#xff0c;这样也导致set集合里面的元素是不能重复的&#xff0c;因为这一个特性&#xff0c;所以我们经常用set集合进行去重操作&#xff0c;我们下面以一个简单的例子说明set集合是如何进行去重的。 创建去…

缺少构造方法:Cause java.sql.SQLDataException Unsupported conversion from LONG to java.sql.Timestamp

今天遇到了一个奇怪的错误&#xff0c;报错如下图所示&#xff1a; org.springframework.dao.DataIntegrityViolationException: Error attempting to get column question_id from result set. Cause: java.sql.SQLDataException: Unsupported conversion from LONG to java…

SpringBoot瘦身打包部署

一、前言 最近做的项目由于引入第三方库导致在运行mvn clean package 打jar时&#xff0c;编译出来的 Jar 包很大&#xff08;服务器多达500MB&#xff09;。 二、瘦身前的Jar包 SpringBoot编译出来的Jar包中&#xff0c;磁盘占用大的&#xff0c;是一些外部依赖库&#xff…

XShell直接拖拽文件到服务器,不使用Xftp等文件上传工具

很多情况下&#xff0c;我们使用 Xshell 工具时&#xff0c;如果遇到文件的上传和下载会不可避免的要用到另外一个工具 Xftp&#xff0c;但是频繁的使用 Xftp 会比较麻烦&#xff0c;那么有没有一种更加直接简单的方法呢&#xff1f; 当我们所需要上传的文件比较小的时候&…

System.getProperty()方法获取系统变量

今天在阅读JDBC的DriverManager类源码时&#xff0c;看到了这么一句代码&#xff1a; System.getProperty(“jdbc.drivers”)&#xff1b;getProperty()这个方法是获取指定键指示的系统属性的&#xff0c;也就是说上面的代码获取的是jdbc.drivers这个属性。我写了个测试测试输…

局部变量为什么必须赋值才可以使用

在java内存模型中规定&#xff0c;一个新的变量只能在主存中初始化&#xff0c;不允许在工作内存中直接使用一个未被初始化的变量。 工作内存可以理解为局部变量定义的内存区域&#xff0c;也就是线程的工作内存。所谓局部变量就是线程私有的不共享的空间。 类加载准备阶段 类变…

Java 赋值 “=” 讲解

前言 我们从接触java第一天&#xff0c;就是到 是赋值的意思&#xff0c;把等号右边结果的值&#xff0c;赋给等号左边的变量&#xff0c;那具体是怎样赋值呢&#xff1f;你有了解过吗&#xff1f; 1.0版本 大家都知道&#xff0c;java中有 8大基本类型&#xff0c;对于基本…

Linux 系统管理命令:时间、进程、网络、磁盘、关机重启等 top命令用法详解

文章目录系统管理常用命令1. 日期1.1 查看日历: cal1.2 查看/设置时间: date2. 进程2.1 查看进程信息: ps2.2 动态显示进程信息: top2.3 终止进程: kill2.4 服务的管理: service3. 网络3.1 网卡信息查询与配置: ifconfig3.2 检测远程主机连通性: ping3.3 查看网络状态(监听端口…

Java8中计算时间的四种方式及区别Period、Duration、ChronoUnit、Until 时间区间Duration的简单使用

一.简述 在Java8中&#xff0c;我们可以使用以下类来计算日期时间差异&#xff1a; 1.Period 2.Duration 3.ChronoUnit二.Period类 Period类计算只有年、月、日 计算的是LocalDate两个时间间隔的年月日 public static void main(String[] args) {LocalDate startTime Loc…

[JAVA基础] 成员变量和局部变量(一看就懂的总结归纳篇)

引言 成员变量和局部变量在每种编程语言中都有涉及&#xff0c;如果之前了解过其他语言的成员变量或者局部变量&#xff0c;那么在学习java中的成员变量和局部变量时可以看看有那些联系和不同&#xff0c;这一块的东西也不能说难&#xff0c;如果第一次接触可能会感觉有点乱&a…

【Java多线程】内存模型JMM—主内存与工作内存分析

文章目录JAVA内存模型JVM主内存与工作内存描述JVM内存间交互规则JVM先行发生原则内存交互基本操作的 3 个特性原子性(Atomicity)可见性(Visibility)有序性(Ordering)上述内存模型与Java多线程之间的问题JAVA内存模型 共享变量&#xff1a;如果一个变量在多个线程的工作内存中都…

SpringBoot配置MyBatis的sql执行超时时间(mysql)

当某些sql因为不知名原因堵塞时&#xff0c;为了不影响后台服务运行&#xff0c;想要给sql增加执行时间限制&#xff0c;超时后就抛异常&#xff0c;保证后台线程不会因为sql堵塞而堵塞。 方法一 yml全局配置&#xff1a;单数据源可以&#xff0c;多数据源时会失效 方法二 j…

HTTP协议中的302,303状态码

之前也只知道302,303是请求重定向,但是当被问到302,303的具体区别是什么的时候我有点迷,现在就为了加强记忆,来了解下具体情况: 302是http1.0的内容&#xff0c;303是http1.1的内容。301和302本来在规范中是不允许重定向时改变请求方法的&#xff08;将POST改为GET&#xff09…

Spring自带工具类(断言、ObjectUtils、FileCopyUtils、ResourceUtils、StreamUtils、ReflectionUtils、AopUtils、AopCont)

文章目录断言对象、数组、集合文件、资源、IO 流反射、AOP断言 断言是一个逻辑判断&#xff0c;用于检查不应该发生的情况Assert 关键字在 JDK1.4 中引入&#xff0c;可通过 JVM 参数-enableassertions开启SpringBoot 中提供了 Assert 断言工具类&#xff0c;通常用于数据合法…