在业务开发中遇到的树形结构(部门、区域、职位),递归处理。
文章目录
- 概要
- 对象结构示例
- 完整示例
- 小结
概要
本文主要记录在树形结构中会遇到的问题,
使用部门结构讲解,main方法进行演示。
1、获取部门树结构
2、根据部门id获取所有下级
3、根据部门id获取上级部门
4、根据部门id获取类似面包屑(总公司/技术部/技术一部)
对象结构示例
@Data
static class Department{Integer id;String name;Integer parentId;
}
可能会用到的依赖(非必要)
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.28</version>
</dependency>
完整示例
package com.example.springboot_demo;import com.alibaba.fastjson.JSONObject;
import lombok.Data;import java.util.*;
import java.util.stream.Collectors;public class TreeTest {public static void main(String[] args) {List<DepartmentVO> departments = Arrays.asList(new DepartmentVO(1, "总公司", 0),new DepartmentVO(2, "技术部", 1),new DepartmentVO(3, "技术一部", 2),new DepartmentVO(4, "技术二部", 2),new DepartmentVO(5, "业务部", 1),new DepartmentVO(6, "业务一组", 5),new DepartmentVO(7, "业务二组", 5),new DepartmentVO(8, "业务二组一部", 7));//根据id获取所有下级List<DepartmentVO> subList = new ArrayList<>();getSubList(2,departments,subList);System.out.println(JSONObject.toJSON(subList));//根据id获取所有上级List<DepartmentVO> supList = new ArrayList<>();findSupList(3,departments,supList);System.out.println(JSONObject.toJSON(supList));//根据id获取所有上级名字 类似面包屑结构 总公司/技术部/技术一部StringBuilder sb = new StringBuilder();findSupName(3,departments,sb);System.out.println(sb);//返回部门树形结构List<DepartmentVO> departmentVOS = buildTree(departments);System.out.println(JSONObject.toJSON(departmentVOS));}static List<DepartmentVO> buildTree(List<DepartmentVO> departments){//构建根节点List<DepartmentVO> rootNode = departments.stream().filter(i -> Objects.equals(i.getParentId(), 0)).collect(Collectors.toList());//用根节点去递归找到childfor (DepartmentVO department : rootNode) {department.setChild(buildTree(department.getId(), departments));}return rootNode;}static List<DepartmentVO> buildTree(Integer deptId, List<DepartmentVO> departments){List<DepartmentVO> childList = new ArrayList<>();for (DepartmentVO dept : departments) {// 遍历所有属于父级节点的子节点if (Objects.equals(deptId, dept.getParentId())) {childList.add(dept);}}//然后给所有子节点添加子节点for (DepartmentVO dept : childList) {// 遍历所有属于父级节点的子节点dept.setChild(buildTree(dept.getId(), departments));}return childList;}//根据部门id查找所有下级部门static void getSubList(Integer id, List<DepartmentVO> departments, List<DepartmentVO> result) {for (DepartmentVO departmentVO : departments) {if (Objects.equals(departmentVO.getParentId(), id)) {getSubList(departmentVO.getId(), departments, result);result.add(departmentVO);}}}//根据部门id 获取所有上级static void findSupList(Integer deptId, List<DepartmentVO> departments, List<DepartmentVO> result){DepartmentVO departmentVO = departments.stream().filter(i -> Objects.equals(deptId, i.getId())).findFirst().orElse(null);if (departmentVO == null) {return;}findSupList(departmentVO.getParentId(), departments, result);result.add(departmentVO);}// 如 总公司/技术部/技术一部static void findSupName(Integer deptId, List<DepartmentVO> departments, StringBuilder sb){DepartmentVO departmentVO = departments.stream().filter(i -> Objects.equals(deptId, i.getId())).findFirst().orElse(null);if (departmentVO == null) {return;}findSupName(departmentVO.getParentId(), departments, sb);if(sb.length() > 0){sb.append("/");}sb.append(departmentVO.getName());}@Datastatic class DepartmentVO{Integer id;String name;Integer parentId;List<DepartmentVO> child;public DepartmentVO(Integer id, String name, Integer parentId) {this.id = id;this.name = name;this.parentId = parentId;}}}
控制台输出:
根据id获取所有下级:[{"name":"技术一部","id":3,"parentId":2},{"name":"技术二部","id":4,"parentId":2}]
根据id获取所有上级:[{"name":"总公司","id":1,"parentId":0},{"name":"技术部","id":2,"parentId":1},{"name":"技术一部","id":3,"parentId":2}]
根据id获取所有上级名字:总公司/技术部/技术一部
返回部门树形结构:[{"name":"总公司","id":1,"parentId":0,"child":[{"name":"技术部","id":2,"parentId":1,"child":[{"name":"技术一部","id":3,"parentId":2,"child":[]},{"name":"技术二部","id":4,"parentId":2,"child":[]}]},{"name":"业务部","id":5,"parentId":1,"child":[{"name":"业务一组","id":6,"parentId":5,"child":[]},{"name":"业务二组","id":7,"parentId":5,"child":[{"name":"业务二组一部","id":8,"parentId":7,"child":[]}]}]}]}]
小结
对于树形结构、结构都是大同小异,具体的场景还需要进行对应的校验。
如果数据量庞大时、建议把List替换为Map结构。处理更快。
相关文章:
在业务开发中遇到的树形结构(部门、区域、职位),递归处理。
文章目录 概要对象结构示例完整示例小结 概要 本文主要记录在树形结构中会遇到的问题, 使用部门结构讲解,main方法进行演示。 1、获取部门树结构 2、根据部门id获取所有下级 3、根据部门id获取上级部门 4、根据部门id获取类似面包屑(总公司…...
张量-算术操作函数
tf.add(x,y,name None)求和函数 示例代码如下: import tensorflow.compat.v1 as tf tf.disable_v2_behavior()x 1 y 2a tf.add(x,y)with tf.Session() as sess:print(sess.run(a)) tf.subtract(x,y,name None)减法函数 示例代码如下: import tensorflow.compat.v1 as …...
虚拟展厅有什么重要意义,了解虚拟展厅在宣传中的应用
引言: 随着科技的不断进步,虚拟展厅已经逐渐成为展览行业的重要一环。虚拟展厅是一种数字化平台,为观众提供了与传统展览完全不同的体验。 一.虚拟展厅的定义 虚拟展厅是一个通过互联网和虚拟现实技术创建的数字展示空间&#x…...
华为OD机试真题-补种未成活胡杨(Java/C++/Go/Python)
华为OD机试真题-补种未成活胡杨(Java/C++/Go/Python) 题目描述 近些年来,我国防沙治沙取得显著成果。某沙漠新种植N棵胡杨(编号1-N),排成一排。 一个月后,有M棵胡杨未能成活。现可补种胡杨K棵,请问如何补种(只能补种,不能新种),可以得到最多的连续胡杨树? 输入…...
Java卷上天,可以转行干什么?
小刚是某名企里的一位有5年经验的高级Java开发工程师,每天沉重的的工作让他疲惫不堪,让他萌生出想换工作的心理,但是转行其他工作他又不清楚该找什么样的工作 因为JAVA 这几年的更新实在是太太太……快了,JAVA 8 都还没用多久&am…...
Pyside6 安装和简单界面开发
Pyside6 安装和简单界面开发 Pyside6介绍Pysied6开发环境搭建Python安装Pysied6安装 Pyside6界面开发简单界面设计界面设计界面编译 编写界面初始化代码软件打包 Pyside6介绍 对于Python的GUI开发来说,Python自带的可视化编程模块的功能较弱,PySide是跨…...
python读取vivo手机截图,将满屏图片文件移动别的路径
问题之初 python读取vivo手机截图, 将满屏图片文件移动别的路径好多这样的图片,占用手机大量的内存,食之无味弃之可惜!那么会复制粘贴👀代码的我们我们今天就把这些图片筛选清理掉。 这段代码 原有逻辑的基础上&…...
【一周安全资讯1007】多项信息安全国家标准10月1日起实施;GitLab发布紧急安全补丁修复高危漏洞
要闻速览 1.以下信息安全国家标准10月1日起实施 2.GitLab发布紧急安全补丁修复高危漏洞 3.主流显卡全中招!GPU.zip侧信道攻击可泄漏敏感数据 4.MOVEit漏洞导致美国900所院校学生信息发生大规模泄露 5.法国太空和国防供应商Exail遭黑客攻击,泄露大量敏感…...
2023年09月个人工作生活总结
本文为 2023 年 9 月工作生活总结。 研发编码 Alpine 容器 某工程部署于alpine镜像,当初看上是因为其体积小,其它微服务,在250MB左右,但那个工程只用50MB。最近发现时间戳转换不正确。对于同一时间字符串转时间戳函数࿰…...
现货白银图表分析的依据
现货白银的行情图表分析其实与股票的差不多,投资者可以结合均线、k线的变化,来分析实时的行情走势。当走势图的均线呈多头排列,即短期、中期、长期均线依次从上到下排列并向右上方运行,且白银价格沿各均线向右上方拉升,…...
python多线程与多进程
多线程与多进程 一, 什么是进程, 什么是线程? 进程: 运行中的程序. 每次我们执行一个程序, 咱们的操作系统对自动的为这个程序准备一些必要的资源(例如, 分配内存, 创建一个能够执行的线程. ) 线程: 程序内, 可以直接被CPU调度的执行过程. 是操作系统能够进行运算调度…...
62从零开始学Java之时间相关的类都有哪些?
作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 我们在开发时,除了数字、数学这样的常用API之外,还有日期时间类,更…...
【Leetcode】买卖股票系列
121. 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔…...
SLAM面试笔记(8) — 计算机视觉面试题
目录 问题1:目标检测的算法分类 问题2:卷积神经网络的组成 问题3:输入层的作用 问题4:卷积层作用 问题5:卷积核类型 问题6:11卷积核作用 问题7:卷积核是否越大越好 问题8:棋…...
聊聊MySQL面试常问名词回表、索引覆盖,最左匹配
文章目录 1. 前言2. 回表操作 Index Lookup2.1 什么是回表2.2 回表的成本2.3 如何避免回表 3. 索引覆盖 Covering Index3.1 什么是索引覆盖3.2 索引覆盖的优点3.3 如何使用索引覆盖 4. 最左匹配原则(Leftmost Prefix Match)4.1 什么是最左匹配原则4.2 最…...
【面试】C/C++面试八股
C/C面试八股 编译过程的四个阶段C和C语言的区别简单介绍一下三大特性多态的实现原理虚函数的构成原理虚函数的调用原理虚表指针在什么地方进行初始化的?构造函数为什么不能是虚函数为什么建议将析构函数设为虚函数虚函数和纯虚函数的区别抽象类类对象的对象模型内存…...
学习记忆——数学篇——算术——无理数
谐音记忆法 2 \sqrt{2} 2 ≈1.41421:意思意思而已;意思意思; 3 \sqrt{3} 3 ≈1.7320:—起生鹅蛋;一起生儿; 5 \sqrt{5} 5 ≈2.2360679:两鹅生六蛋(送)六妻舅;儿儿生…...
python协程和任务
协程概念引入 协程是我要重点去讲解的一个知识点. 它能够更加高效的利用CPU. 其实, 我们能够高效的利用多线程来完成爬虫其实已经很6了. 但是, 从某种角度讲, 线程的执行效率真的就无敌了么? 我们真的充分的利用CPU资源了么? 非也~ 比如, 我们来看下面这个例子. 我们…...
visual studio code配置anaconda3的python虚拟环境
参考: Visual Studio Code配置anconda3虚拟环境 - 知乎...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
