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());
		
	//返回树结构的list
	return 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": []
                }
            ]
        }
    ]
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt 软件封装与打包

1. Qt 软件封装 1、首先以 release 方式进行编译&#xff0c;将生成的 CloudOne.exe 文件复制到 D:\CloudApp 文件夹&#xff08;自行创建&#xff09; 2、打开 Qt 命令行工具&#xff08;如下图所示&#xff09;&#xff0c;并按顺序输入如下指令 cd D:\CloudApp windeployq…

Spring Boot 笔记 019 创建接口_文件上传

1.1 创建阿里OSS bucket OSS Java SDK 兼容性和示例代码_对象存储(OSS)-阿里云帮助中心 (aliyun.com) 1.2 编写工具类 package com.geji.utils;import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun…

每日一题——数字翻转

题目; 这道题看似是很简单的回文数 实则就是很简单的回文数 但是需要注意的一点是负数 可以在开头就进行判断&#xff0c;如果N<0的话就令N-N&#xff0c;将所有数都转成正数就好办了 上代码&#xff1a; #include <iostream> #include<string> #include<…

算法沉淀——哈希算法(leetcode真题剖析)

算法沉淀——哈希算法 01.两数之和02.判定是否互为字符重排03.存在重复元素04.存在重复元素 II05.字母异位词分组 哈希算法&#xff08;Hash Algorithm&#xff09;是一种将任意长度的输入&#xff08;也称为消息&#xff09;映射为固定长度的输出的算法。这个输出通常称为哈希…

Spring Security学习(四)——登陆认证(包括自定义登录页)

前言 和前面的文章隔了很长时间才更新Spring Security系列&#xff0c;主要原因一个是之前太忙了&#xff0c;把项目都忙完了&#xff0c;赶上春节假期&#xff0c;就慢慢研究。Spring Security的体系非常复杂&#xff0c;一口吃不了热豆腐&#xff0c;没办法速成&#xff0c;…

微服务—ES数据同步

目录 数据同步 问题分析 方案1. 同步调用 方案2. 异步通知 方案3. 监听binlog​编辑 各方案对比 案例——利用MQ实现数据同步 步骤1. 导入hotel-admin项目 步骤2. 声明交换机、队列 步骤3. 发送MQ消息 步骤4. 接收MQ消息 步骤5. 测试同步功能 数据同步 elasticsea…

八、键盘响应

之前博文格式已经固定&#xff0c;这里就不在赘述了&#xff0c;直接把核心代码进行解释一下即可&#xff0c;仅作为小笔记而已 项目实现功能&#xff1a; 按下键盘0&#xff0c;显示原始图像 按下键盘1&#xff0c;显示原始图像的灰度图 按下键盘2&#xff0c;显示原始图像的…

Python-To-Do-List

今天跟着油管学习创建了简单的代办事项列表应用程序&#xff0c;使用了python的tkinter库来制作图形用户界面&#xff08;GUI&#xff09; 1. 导入tkinter库 python Copy code import tkinter from tkinter import * 这两行导入了tkinter模块&#xff0c;它是Python的标准GUI库…

六、Redis之数据持久化及高频面试题

6.1 数据持久化 官网文档地址&#xff1a;https://redis.io/docs/manual/persistence/ Redis提供了主要提供了 2 种不同形式的持久化方式&#xff1a; RDB&#xff08;Redis数据库&#xff09;&#xff1a;RDB 持久性以指定的时间间隔执行数据集的时间点快照。AOF&#xff0…

django CBV 与 DRF APIView源码分析

django CBV源码分析 在django框架中&#xff0c;视图层中的逻辑即可以使用函数处理也可以使用类进行处理&#xff0c;如果在视图层中使用函数处理请求&#xff0c;就是FBV(function base views)&#xff0c;如果在视图层中使用类处理请求&#xff0c;就是CBV(class base views…

微信,支付宝在线换钱平台系统源码

探索全新、全开源的在线换钱系统源码&#xff0c;它将以前所未有的方式改变您的支付体验。我们为您精心打造了一个集简单易用与安全高效于一身的优质产品&#xff0c;它采用最新的技术开发&#xff0c;为您带来前所未有的便捷与安心。 这款在线换钱系统源码设计直观&#xff0…

【大数据Hive】hive 表设计常用优化策略

目录 一、前言 二、hive 普通表查询原理 2.1 操作演示说明 2.1.1 创建一张表&#xff0c;并加载数据 2.1.2 统计3月24号的登录人数 2.1.3 查询原理过程总结 2.2 普通表结构带来的问题 三、hive分区表设计 3.1 区表结构 - 分区设计思想 3.2 操作演示 3.2.1 创建分区表…

每日一题(数字颠倒,单词倒排)

数字颠倒_牛客题霸_牛客网 (nowcoder.com) #include <stdio.h>int main() {char arr[100];gets(arr);int lenstrlen(arr);for(int ilen-1;i>0;i--){printf("%c",arr[i]);}return 0; } 单词倒排_牛客题霸_牛客网 (nowcoder.com) #include <stdio.h> #…

《Java 简易速速上手小册》第4章:Java 中的异常处理(2024 最新版)

文章目录 4.1 异常类型和错误 - 遇见你的小怪兽4.1.1 基础知识4.1.2 重点案例&#xff1a;文件读取处理4.1.3 拓展案例 1&#xff1a;处理空指针异常4.1.4 拓展案例 2&#xff1a;捕获多个异常 4.2 异常处理机制 - 穿上你的超级英雄斗篷4.2.1 基础知识4.2.2 重点案例&#xff1…

Vuex 模块的详解

Vuex 模块是将 store 分割成多个模块的一种方式&#xff0c;每个模块都有自己的状态、mutations、actions 和 getters。这有助于更好地组织和管理应用程序的状态。 创建模块&#xff1a; 首先&#xff0c;需要创建一个模块。可以在 store 中定义一个新的模块对象&#xff0c…

python小项目----多重剪切板

代码&#xff1a; import shelve,pyperclip,sysimport mcbmcbShelfshelve.open(mcb)# 保存剪切板内容 if len(sys.argv)3 and sys.argv[1].lower()save:#剪切板的内容保存到第三个参数中mcbShelf[sys.argv[2]]pyperclip.paste()print("你的剪切板中的内容将被保存到mcbSh…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 2月14日,星期三

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年2月14日 星期三 农历正月初五 1、 第十四届全国冬季运动会将于17日开幕&#xff0c;部分赛事今天起陆续开赛。 2、 2024年购房政策将进一步宽松&#xff0c;专家称今年买房性价比更高。 3、 春节档票房突破45亿元&#…

算法学习——LeetCode力扣回溯篇2

算法学习——LeetCode力扣回溯篇2 40. 组合总和 II 40. 组合总和 II - 力扣&#xff08;LeetCode&#xff09; 描述 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字…

(二)【Jmeter】专栏实战项目靶场drupal部署

该专栏后续实战示例&#xff0c;都以该篇部署的项目展开操作。 前置条件 参考“&#xff08;一&#xff09;【Jmeter】JDK及Jmeter的安装部署及简单配置” 安装部署Jmeter&#xff0c;从文章最后下载“Postman、Rancher.ova、VirtualBox-7.0.12-159484-Win.exe、Xshell-7.0.01…

CMU和ETH联合研发了一个名为 「敏捷但安全」的新框架,为四足机器人在复杂环境中实现高速运动提供了解决方案

在高速机器人运动领域&#xff0c;实现同时兼顾速度和安全一直是一大挑战。但现在&#xff0c;卡内基梅隆大学&#xff08;CMU&#xff09;和苏黎世联邦理工学院&#xff08;ETH&#xff09;的研究团队带来了突破性进展。他们开发的新型四足机器人算法&#xff0c;不仅能在复杂…