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.hqwc.cn/news/468530.html

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

相关文章

LeetCode、72. 编辑距离【中等,二维DP】

文章目录 前言LeetCode、72. 编辑距离【中等&#xff0c;二维DP】题目链接与分类二维DP 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容…

幻兽帕鲁服务器配置参数说明(Palworld官方汉化)

创建幻兽帕鲁服务器配置参数说明&#xff0c;Palworld服务器配置参数与解释&#xff0c;阿腾云atengyun.com分享&#xff1a; 自建幻兽帕鲁服务器教程&#xff1a; 阿里云教程 https://t.aliyun.com/U/bLynLC腾讯云教程 https://curl.qcloud.com/oRMoSucP 幻兽帕鲁服务器 幻…

34 张图详解网络设备知识

网络其实很简单&#xff0c;就是一堆设备连接在一起&#xff0c;然后在上面跑各种网络协议&#xff0c;实现设备之间的网络互通。其中第一步便是把所有设备按照一定的规则连接起来。这些设备可能是路由器、交换机、防火墙等网络设备&#xff0c;也可能是服务器、电脑、手机等需…

Pb协议的接口测试

Protocol Buffers 是谷歌开源的序列化与反序列化框架。它与语言无关、平台无关、具有可扩展的机制。用于序列化结构化数据&#xff0c;此工具对标 XML &#xff0c;支持自动编码&#xff0c;解码。比 XML 性能好&#xff0c;且数据易于解析。更多有关工具的介绍可参考官网。 P…

ClickHouse--07--SQL DDL 操作

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 SQL DDL 操作1 创建库2 查看数据库3 删除库4 创建表5 查看表6 查看表的定义7 查看表的字段8 删除表9 修改表9.1 添加列9.2 删除列9.3 清空列9.4 给列修改注释9.5 修…

攻防世界——re2-cpp-is-awesome

64位 我先用虚拟机跑了一下这个程序&#xff0c;结果输出一串字符串flag ——没用 IDA打开后 F5也没有什么可看的 那我们就F12查看字符串找可疑信息 这里一下就看见了 __int64 __fastcall main(int a1, char **a2, char **a3) {char *v3; // rbx__int64 v4; // rax__int64 v…

I.MX6U C语言运行环境构建及驱动开发格式

1.设置处理器模式 设置6ULL处于SVC模式下。设置下CPSR寄存器的bit4-0,也就是M[4:0]为100110x13.。读写状态寄存器需要用到MRS和MSR指令。MRS将CPSR寄存器数据读出到通用寄存器里面&#xff0c;MSR指令将通用寄存器的值写入到CPSR寄存器里面去。 2.设置SP指针 SP可以指向内部…

在小区门口开什么店比较好?把握商机从这里开始

作为一位资深的鲜奶吧创业者&#xff0c;我已经在这个行业摸爬滚打了五年。这五年的时间里&#xff0c;我见证了社区商业的繁荣与变迁&#xff0c;也深刻体会到了在小区门口开店的商机与挑战。今天&#xff0c;我想和大家分享一些关于在小区门口开店的见解&#xff0c;特别是针…

LLVM的中间表示

概括 选择编译器IR的决策很重要&#xff0c;它决定了优化过程将拥有多少信息来使代码运行得更快。 一方面非常高层级的IR允许优化器轻松地提取原始源代码的相关信息。 另一方面&#xff0c;低层的IR更加贴近目标机器&#xff0c;这样编译器更容易为特定的硬件生成相应的代码…

高斯模糊滤镜

高斯模糊滤镜 import cv2# 读取图像 image cv2.imread(1.jpg)# 高斯模糊滤镜 blurred cv2.GaussianBlur(image, (15, 15), 0)# 保存处理后的图像 cv2.imwrite(blurred_image.jpg, blurred)# 显示原始图像和处理后的图像 cv2.imshow(Original Image, image) cv2.imshow(Blurre…

Java的Cloneable接口和深拷贝

Java 中内置了一些很有用的接口, Clonable 就是其中之一。 Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 "拷贝"。 但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常。 浅拷贝&#xff…

C# CAD2016 判断多边形的方向正时针或逆时针旋转

方法一&#xff1a;基于相邻顶点相对位置判断顺时针排列 // 计算当前子序列是否为顺时针排列 for (int i 1; i < outerPoints.Count; i) {int index (startVertexIndex i) % outerPoints.Count;int prevIndex (startVertexIndex i - 1) % outerPoints.Count;Point2d c…