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 改变后才…

Function.identity()

Function.identity()是什么&#xff1f; // 将Stream转换成容器或Map Stream<String> stream Stream.of("I", "love", "you", "too"); Map<String, Integer> map stream.collect(Collectors.toMap(Function.identity()…

Java 异常——Exception详解

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

时间复杂度和空间复杂度的计算方法

什么是算法 算法的定义是这样的&#xff1a;解题方案的准确而完善的描述&#xff0c;是一系列解决问题的清晰指令。巴拉巴拉的&#xff0c;虽然是一小句但还是不想看&#xff08;题外话&#xff1a;有时候吧专业名词记下来面试的时候还是挺有用的&#xff09;&#xff0c;其实…

Vue中嵌入html页面并相互通信

Vue中嵌入html页面并相互通信 引言&#xff1a;由于最近工作中用到了大量的Iframe去集成一些只能通过原生html、css、js开发的功能接口&#xff0c;因此特意做一下过程记录的笔记。方便交流学习使用。 1. Vue中嵌入Html的方式 1.1 html的页面是单独的一个服务&#xff0c;有…

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

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

ByteArrayOutputStream详解

介绍&#xff1a; ByteArrayOutputStream 对byte类型数据进行写入的类 相当于一个中间缓冲层&#xff0c;将类写入到文件等其他outputStream。它是对字节进行操作&#xff0c;属于内存操作流 源码解析&#xff1a; public class ByteArrayOutputStream extends OutputStream…

MySQL如何查询表中重复的数据

一、查询重复记录 例&#xff1a;查询员工表里出现重复姓名的记录 思路&#xff1a; 1、查看重复记录&#xff0c;首先要使用分组函数&#xff08;group by&#xff09;&#xff0c;再用聚合函数中的计数函数count(name)给姓名列计数&#xff0c;且使用group by 后不可使用* …

Java中的Socket的用法——Socket、NioSocket

一、Java Socket的分类 Java中的Socket分为普通的Socket和NioSocket。 二、普通Socket Java中的网络通信时通过Socket实现的&#xff0c;Socket分为ServerSocket和Socket两大类&#xff0c;ServerSocket用于服务器端&#xff0c;可以通过accept方法监听请求&#xff0c;监听…

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…

如何在高版本谷歌Chrome浏览器中用VLC播放海康、大华RTSP实时视频?

一、背景 随着互联网基础设施的完善以及4G、5G等技术的大规模商用&#xff0c;在Chrome、Firefox、Edge等浏览器播放RTSP视频流也慢慢成为了信息化系统的行业标准。 早些年还可用VLC播放器在网页中播放RTSP视频流&#xff0c;好景不长&#xff0c;2015年Chrome、Firefox等浏览…

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集合是如何进行去重的。 创建去…

BigDecimal 类的 compareTo() 和 equals()方法

BigDecimal 类的 compareTo() 和 equals()方法 1. compareTo()源码 /*** Compares this BigDecimal with the specified BigDecimal. * Two BigDecimal objects that are equal in value but have * a different scale (like 2.0 and 2.00) are considered equal* by this met…

缺少构造方法: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…

Collectors.reducing总结Collectors.mapping+Collectors.reducing+TreeSet等等

Collectors.reducing总结 1. 方法签名 一个参数 public static <T> Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op)参数说明 BinaryOperator op 归集操作函数 输入参数T返回T 测试代码 我们这里实现一个简单的求和功能&#xff0…

vim退出快捷键

退出vim的快捷键 不需要进入命令编辑模式 按住shift zz 保存退出 zq 不保存退出&#xff0c;q表示放弃 之所以按住shift&#xff0c;其实是切换大小写 在命令编辑模式下&#xff1a; :q 不保存退出 :q! 不保存强制退出 :wq 保存退出&#xff0c;w表示写入&#xff0c;…

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; 当我们所需要上传的文件比较小的时候&…