java实现多级目录树(递归实现)

一.应用场景

有时候需要我们后台给前台传树结构的数据,要怎么查询? 怎么返回数据呢?

二.数据库表设计以及数据内容(以部门举例)

id            主键
parent_id     父级部门id
depart_name   部门名词
sort          部门排序

在这里插入图片描述

三.实体类

@Data
public class KunKun implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty("部门id")private String id;@ApiModelProperty("父级部门id")private String parentId;@ApiModelProperty("机构/部门名称")private String departName;@ApiModelProperty("子级部门的集合")private List<KunKun> children;
}

四.代码实现

public void selectKunTree() {//查询部门信息,获取全部部门信息List<KunKun> kunList = xxxxMapper.selectList() ;//组装成树形结构//找到所有的一级分类(也就是树的根节点)List<KunKun> ikuns = kunList.stream().filter(ikun ->ikun.getParentId() == 0).map((menu) -> {menu.setChildren(getChildrens(menu,kunList));return menu;}).sorted((menu1,menu2)-> {//如果你查询的时候就排好序了就不用写这里return menu1.getSort() - menu2.getSort();}).collect(Collectors.tolist());//返回树结构的listreturn ikuns;}//递归方法
private List<KunKun> getChildrens(KunKun root,List<KunKun> all){List<KunKun> children = all.stream().filter(ikun -> { return ikun.getParentId() == root.getId();}).map(ikun  -> { //找子部门ikun.setChildren(getChildrens(ikun ,all));return categoryEntity;}).sorted( (menu1 ,menu2)return menu1.getSort - menu2.getSort() }).collect(Collectors .tolist());return children;
}

=========================

多个一级id场景

在这里插入图片描述

实现思路

获取所有的分类。
获取所有分类的id集合。使用stream()实现,stream使用教程
获取一级分类信息。同样使用stream()实现。
循环一级分类,在循环中将一级分类添加子分类,并且将一级分类加入返回的树结构中(备注:不加入返回的树结构中也行,直接返回步骤3的分类信息一样)。
重点是步骤4中将一级分类添加子分类,并且子分类在添加子子分类,子子分类再添加子子子分类··········等等,实现过程使用递归即可。
步骤5的实现过程:写一个递归方法,往当前节点添加子节点,首先获取当前节点的字节点集合,然后把这个集合放入到当前节点子节点属性中,接着再次调用当前递归的方法,把刚获取到的子节点当成新当前节点,获取新当前节点的新子节点,注意再次调用当前递归的方法,把刚获取到的子节点当成新当前节点之前首先判断新当前节点有没有子节点(判断方法:获取当前节点的字节点数组,根据数组的size()>0?判断是否有子节点),如果没有就不用递归。
总结:1-4是数据准备,5-6是实现递归(当前节点添加子节点的递归)。

代码展示

  1. 主要思路代码
@GetMapping("/list")public Result list() {//所有的分类List<Category> categoryList = categoryService.list();//所有分类id集合List<String> idList = categoryList.stream().map(Category::getId).collect(Collectors.toList());//返回的树分类结果List<Category> treeCategory = new ArrayList<>();//一级分类目录List<Category> categories = categoryList.stream().filter(category -> !idList.contains(category.getParentId())).collect(Collectors.toList());//循环当前一级分类目录for (Category category : categories) {//给当前分类节点 添加 子分类节点addChild(categoryList,category);//当前分类添加完子节点分类之后,添加到返回的树结构中treeCategory.add(category);}//把返回的树结构返回return Result.success(categories);}/*** 给当前分类节点 添加 子分类节点* @param categoryList 所有的分类* @param category 当前分类节点*/public void addChild( List<Category> categoryList,Category category){//循环所有的分类,获取当前节点的所有子节点List<Category> categoryListChild = categoryList.stream().filter(category1 -> category1.getParentId().equals(category.getId())).collect(Collectors.toList());//把当前分类的子节点添加到当前分类category.setChildList(categoryListChild);//再次调用本方法,把当前节点的子节点当成当前节点,继续添加子节点,备注:这样会造成一直循环categoryListChild.forEach(category1 -> {//添加一步,判断当前节点是否有子节点,没有就不循环递归if (haveChild(categoryList,category1)){addChild(categoryList,category1);}});}/*** 判断当前节点 是否存在 子节点* @param categoryList 所有的分类* @param category 当前节点*/public boolean haveChild( List<Category> categoryList,Category category){//获取当前节点的子节点List<Category> categoryListChild = categoryList.stream().filter(category1 -> category1.getParentId().equals(category.getId())).collect(Collectors.toList());//子节点大于0则存在,否则不存在return categoryListChild==null&&categoryListChild.size()>0;
  1. 实体类代码展示
    备注:实体类代码中一定要有一个子节点数组。实体类对用最上面的实体类图片
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Category implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.ID_WORKER_STR)private String id;/*** 类别名称*/private String name;/*** 上级id*/private String parentId;/*** 分类级别*/private Integer type;/*** 子节点数组*/@TableField(exist = false)private List<Category> childList;
}

##吧数据处理返回:

{"code": 200,"msg": "操作成功","data": [{"id": "1","name": "电子产品","parentId": "0","type": 1,"childList": [{"id": "5","name": "笔记本电脑","parentId": "1","type": 2,"childList": [{"id": "21","name": "联想笔记本","parentId": "5","type": 3,"childList": []},{"id": "22","name": "外星人笔记本","parentId": "5","type": 3,"childList": []},{"id": "23","name": "戴尔笔记本","parentId": "5","type": 3,"childList": []}]},{"id": "6","name": "手机","parentId": "1","type": 2,"childList": [{"id": "24","name": "苹果手机","parentId": "6","type": 3,"childList": []},{"id": "25","name": "菠萝手机","parentId": "6","type": 3,"childList": []}]},{"id": "7","name": "耳机","parentId": "1","type": 2,"childList": []},{"id": "8","name": "电子烟","parentId": "1","type": 2,"childList": []}]},{"id": "2","name": "生活用品","parentId": "0","type": 1,"childList": [{"id": "10","name": "椅子","parentId": "2","type": 2,"childList": []},{"id": "11","name": "床","parentId": "2","type": 2,"childList": []},{"id": "19","name": "牙膏","parentId": "2","type": 2,"childList": []},{"id": "20","name": "牙刷","parentId": "2","type": 2,"childList": []},{"id": "9","name": "桌子","parentId": "2","type": 2,"childList": []}]},{"id": "3","name": "卫生用品","parentId": "0","type": 1,"childList": [{"id": "12","name": "卫生纸","parentId": "3","type": 2,"childList": []},{"id": "13","name": "湿巾","parentId": "3","type": 2,"childList": []}]},{"id": "4","name": "学习用品","parentId": "0","type": 1,"childList": [{"id": "14","name": "电子书","parentId": "4","type": 2,"childList": []},{"id": "15","name": "听力光盘","parentId": "4","type": 2,"childList": []},{"id": "16","name": "实体书","parentId": "4","type": 2,"childList": []},{"id": "17","name": "钢笔","parentId": "4","type": 2,"childList": []},{"id": "18","name": "笔记本子","parentId": "4","type": 2,"childList": []}]}]
}

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

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

相关文章

线性判别分析(LDA)

一、说明 LDA 是一种监督降维和分类技术。其主要目的是查找最能分隔数据集中两个或多个类的特征的线性组合。LDA 的主要目标是找到一个较低维度的子空间&#xff0c;该子空间可以最大限度地区分不同类别&#xff0c;同时保留与歧视相关的信息。 LDA 是受监督的&#xff0c;这意…

【Linux】线程概念和线程控制

线程概念 一、理解线程1. Linux中的线程2. 重新定义线程和进程3. 进程地址空间之页表4. 线程和进程切换5. 线程的优点6. 线程的缺点7. 线程异常8. 线程用途9. 线程和进程 二、线程控制1. pthread 线程库&#xff08;1&#xff09;pthread_create()&#xff08;2&#xff09;pth…

哈夫曼树的学习以及实践

哈夫曼树 哈夫曼树的基本了解哈夫曼树的基本概念创建霍夫曼树的思路编码构建的思路代码实现创建HuffmanTree结点初始化HuffmanTree创建霍夫曼树霍夫曼树编码 哈夫曼树的基本了解 给定 n 个 权值 作为 n 个 叶子节点&#xff0c;构造一颗二叉树&#xff0c;若该树的 带权路径长…

LeetCode:83和82.删除排序链表中的重复元素I,II

这两题算是链表的基础题&#xff0c;就遍历删除没啥特点&#xff0c; 83甚至不需要考虑第一个结点的特殊情况&#xff0c;属实是名副其实的easy了 LeetCode&#xff1a;21.合并两个有序链表之第一次的特殊情况-CSDN博客 83. 删除排序链表中的重复元素 - 力扣&#xff08;Lee…

TeamCity创建git项目Timed out 超时的一个解决办法

问题&#xff1a; 当自己&#xff1a; ping github.com从本地推送到远程仓库浏览器浏览www.github.com ——都没有问题 但是在teamcity创建工程的时候就超时&#xff1a; 或者多试几次&#xff0c;终于成功了&#xff0c;然后构建的时候半途超时报错。。。。。 一种解决办…

Vue3快速上手(四)ref之基本类型响应式数据

一、ref之基本类型响应式数据 1.1 基本语法 import { ref } from vuelet x ref(初始值)console.log(xxx --> , x.value);x为一个RefImpl对象&#xff0c;该对象的value属性为实际值&#xff0c;在script里需要操作x.value来改变数据的值&#xff0c;在页面里则可以直接使…

Django学习全纪录:创建第一个Django项目,如何使用Django开发⼀个web应用

导言 在上一篇文章里,我们对Django的开发环境进行了学习以及搭建,在上一篇文章里,同时也为大家介绍了安装、验证、修改默认镜像源等知识。 在这一篇文章里,我们就正式开始我们的Django开发之旅,创建我们的第一个项目,做一些较为简单且必需的前置工作。 如何创建Django项目…

【MySQL】学习约束和使用图形化界面创建表

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-iqtbME2KmWpQFQSt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

RocksDB:高性能键值存储引擎初探

在现代的分布式系统和大数据应用中&#xff0c;一个高效、可靠的存储引擎是不可或缺的。RocksDB&#xff0c;由Facebook于2012年开发并随后开源&#xff0c;正是为了满足这类需求而诞生的。它是一个持久化的键值存储系统&#xff0c;特别适合在闪存&#xff08;Flash&#xff0…

HCIA-HarmonyOS设备开发认证V2.0-轻量系统内核基础-事件event

目录 一、事件基本概念二、事件运行机制三、事件开发流程四、事件使用说明五、事件接口坚持就有收获 一、事件基本概念 事件是一种实现任务间通信的机制&#xff0c;可用于实现任务间的同步&#xff0c;但事件通信只能是事件类型的通信&#xff0c;无数据传输。一个任务可以等…

Linux——网络通信TCP通信常用的接口和tco服务demo

文章目录 TCP通信所需要的套接字socket()bind()listen()acceptconnect() 封装TCP socket TCP通信所需要的套接字 socket() socket()函数主要作用是返回一个描述符&#xff0c;他的作用就是打开一个网络通讯端口&#xff0c;返回的这个描述符其实就可以理解为一个文件描述符&a…

代码随想录刷题笔记 DAY 25 | 组合问题 No.77 | 组合求和III No.216 | 电话号码的字母组合 No.17

文章目录 Day 2501. 组合问题&#xff08;No. 77&#xff09;2.1 题目2.2 笔记2.3 代码 02. 组合求和III&#xff08;No. 216&#xff09;2.1 题目2.2 笔记2.3 代码 03. 电话号码的字母组合&#xff08;No. 17&#xff09;3.1 题目3.2 笔记3.3 代码3.4 补充 Day 25 01. 组合问…

InstantBox:开箱即用的临时 Linux 环境

在云计算和虚拟化技术日益成熟的今天&#xff0c;我们有时需要一个快速、简单、临时的 Linux 环境来进行各种任务。这就是 InstantBox 的用武之地。 什么是 InstantBox&#xff1f; InstantBox 是一个开源项目&#xff0c;它可以快速启动临时的 Linux 系统&#xff0c;并提供…

微软Bing地图获取栅格瓦片或图块

bing地图获取栅格瓦片或图块 获取元数据 https://dev.virtualearth.net/REST/v1/Imagery/Metadata/{imagerySet}?key{BingMapsKey}imagerySet&#xff1a;要为其请求元数据的影像类型。官方说中国支持以下两个值&#xff1a;RoadOnDemand、VibrantDark BingMapsKey&#xff…

669. 修剪二叉搜索树

给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&#xff0c;原有的父代子代关系都应当保留)。…

【前沿技术杂谈:迁移学习】欧洲人工智能法案对人工智能开发者的意义 [2023 年 12 月更新]

【前沿技术杂谈&#xff1a;迁移学习】欧洲人工智能法案对人工智能开发者的意义 [2023 年 12 月更新&#xff3d; 定义、一般原则和禁止做法人工智能系统开发者基于风险的义务固定和通用人工智能开发人员&#xff08;第 3/28 条&#xff09;基础模型的提供者&#xff08;第 28b…

C++笔记:类与对象的语法

文章目录 1 简单认识面向过程与面向对象1.1 面向过程1.2 面向对象 2 类的引入&#xff1a;struct -> class3 类的定义3.1 class 定义类的语法3.2 成员变量的命名建议 4 类的访问限定符4.1 class 和 struct 的区别4.2 C更喜欢用class定义类的原因 5 类的作用域5.1 声明定义合…

Cost S-curve

成本S曲线 Cost S-curve 每个月成本预算&#xff0c;柱形图 每个月成本累积&#xff08;合计&#xff09;&#xff1a;成本S曲线&#xff0c;折线图&#xff0c;但是肯定都是上升的 echarts图表&#xff1a;

java客运管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java客运管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&#…

Java实现中学生家校互联系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生管理模块2.2 课堂表现模块2.3 考试成绩模块2.4 家校留言模块2.5 校园通知模块 三、系统设计3.1 用例设计3.2 实体类设计3.2.1 课堂表现实体类设计3.2.2 考试成绩实体类设计3.2.3 家校留言实体类设计3.2.4 校园通知实…