当前位置: 首页 > news >正文

在业务开发中遇到的树形结构(部门、区域、职位),递归处理。

文章目录

    • 概要
    • 对象结构示例
    • 完整示例
    • 小结

概要

本文主要记录在树形结构中会遇到的问题,
使用部门结构讲解,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结构。处理更快。

相关文章:

在业务开发中遇到的树形结构(部门、区域、职位),递归处理。

文章目录 概要对象结构示例完整示例小结 概要 本文主要记录在树形结构中会遇到的问题&#xff0c; 使用部门结构讲解&#xff0c;main方法进行演示。 1、获取部门树结构 2、根据部门id获取所有下级 3、根据部门id获取上级部门 4、根据部门id获取类似面包屑&#xff08;总公司…...

张量-算术操作函数

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 …...

虚拟展厅有什么重要意义,了解虚拟展厅在宣传中的应用

引言&#xff1a; 随着科技的不断进步&#xff0c;虚拟展厅已经逐渐成为展览行业的重要一环。虚拟展厅是一种数字化平台&#xff0c;为观众提供了与传统展览完全不同的体验。 一&#xff0e;虚拟展厅的定义 虚拟展厅是一个通过互联网和虚拟现实技术创建的数字展示空间&#x…...

华为OD机试真题-补种未成活胡杨(Java/C++/Go/Python)

华为OD机试真题-补种未成活胡杨(Java/C++/Go/Python) 题目描述 近些年来,我国防沙治沙取得显著成果。某沙漠新种植N棵胡杨(编号1-N),排成一排。 一个月后,有M棵胡杨未能成活。现可补种胡杨K棵,请问如何补种(只能补种,不能新种),可以得到最多的连续胡杨树? 输入…...

Java卷上天,可以转行干什么?

小刚是某名企里的一位有5年经验的高级Java开发工程师&#xff0c;每天沉重的的工作让他疲惫不堪&#xff0c;让他萌生出想换工作的心理&#xff0c;但是转行其他工作他又不清楚该找什么样的工作 因为JAVA 这几年的更新实在是太太太……快了&#xff0c;JAVA 8 都还没用多久&am…...

Pyside6 安装和简单界面开发

Pyside6 安装和简单界面开发 Pyside6介绍Pysied6开发环境搭建Python安装Pysied6安装 Pyside6界面开发简单界面设计界面设计界面编译 编写界面初始化代码软件打包 Pyside6介绍 对于Python的GUI开发来说&#xff0c;Python自带的可视化编程模块的功能较弱&#xff0c;PySide是跨…...

python读取vivo手机截图,将满屏图片文件移动别的路径

问题之初 python读取vivo手机截图&#xff0c; 将满屏图片文件移动别的路径好多这样的图片&#xff0c;占用手机大量的内存&#xff0c;食之无味弃之可惜&#xff01;那么会复制粘贴&#x1f440;代码的我们我们今天就把这些图片筛选清理掉。 这段代码 原有逻辑的基础上&…...

【一周安全资讯1007】多项信息安全国家标准10月1日起实施;GitLab发布紧急安全补丁修复高危漏洞

要闻速览 1.以下信息安全国家标准10月1日起实施 2.GitLab发布紧急安全补丁修复高危漏洞 3.主流显卡全中招&#xff01;GPU.zip侧信道攻击可泄漏敏感数据 4.MOVEit漏洞导致美国900所院校学生信息发生大规模泄露 5.法国太空和国防供应商Exail遭黑客攻击&#xff0c;泄露大量敏感…...

2023年09月个人工作生活总结

本文为 2023 年 9 月工作生活总结。 研发编码 Alpine 容器 某工程部署于alpine镜像&#xff0c;当初看上是因为其体积小&#xff0c;其它微服务&#xff0c;在250MB左右&#xff0c;但那个工程只用50MB。最近发现时间戳转换不正确。对于同一时间字符串转时间戳函数&#xff0…...

现货白银图表分析的依据

现货白银的行情图表分析其实与股票的差不多&#xff0c;投资者可以结合均线、k线的变化&#xff0c;来分析实时的行情走势。当走势图的均线呈多头排列&#xff0c;即短期、中期、长期均线依次从上到下排列并向右上方运行&#xff0c;且白银价格沿各均线向右上方拉升&#xff0c…...

python多线程与多进程

多线程与多进程 一, 什么是进程, 什么是线程? ​ 进程: 运行中的程序. 每次我们执行一个程序, 咱们的操作系统对自动的为这个程序准备一些必要的资源(例如, 分配内存, 创建一个能够执行的线程. ) ​ 线程: 程序内, 可以直接被CPU调度的执行过程. 是操作系统能够进行运算调度…...

62从零开始学Java之时间相关的类都有哪些?

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 我们在开发时&#xff0c;除了数字、数学这样的常用API之外&#xff0c;还有日期时间类&#xff0c;更…...

2023年山东安全员c证考试题库及答案解析来了!

...

【Leetcode】买卖股票系列

121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔…...

SLAM面试笔记(8) — 计算机视觉面试题

目录 问题1&#xff1a;目标检测的算法分类 问题2&#xff1a;卷积神经网络的组成 问题3&#xff1a;输入层的作用 问题4&#xff1a;卷积层作用 问题5&#xff1a;卷积核类型 问题6&#xff1a;11卷积核作用 问题7&#xff1a;卷积核是否越大越好 问题8&#xff1a;棋…...

聊聊MySQL面试常问名词回表、索引覆盖,最左匹配

文章目录 1. 前言2. 回表操作 Index Lookup2.1 什么是回表2.2 回表的成本2.3 如何避免回表 3. 索引覆盖 Covering Index3.1 什么是索引覆盖3.2 索引覆盖的优点3.3 如何使用索引覆盖 4. 最左匹配原则&#xff08;Leftmost Prefix Match&#xff09;4.1 什么是最左匹配原则4.2 最…...

【面试】C/C++面试八股

C/C面试八股 编译过程的四个阶段C和C语言的区别简单介绍一下三大特性多态的实现原理虚函数的构成原理虚函数的调用原理虚表指针在什么地方进行初始化的&#xff1f;构造函数为什么不能是虚函数为什么建议将析构函数设为虚函数虚函数和纯虚函数的区别抽象类类对象的对象模型内存…...

学习记忆——数学篇——算术——无理数

谐音记忆法 2 \sqrt{2} 2 ​≈1.41421&#xff1a;意思意思而已&#xff1b;意思意思&#xff1b; 3 \sqrt{3} 3 ​≈1.7320&#xff1a;—起生鹅蛋&#xff1b;一起生儿&#xff1b; 5 \sqrt{5} 5 ​≈2.2360679&#xff1a;两鹅生六蛋(送)六妻舅&#xff1b;儿儿生&#xf…...

python协程和任务

协程概念引入 ​ 协程是我要重点去讲解的一个知识点. 它能够更加高效的利用CPU. ​ 其实, 我们能够高效的利用多线程来完成爬虫其实已经很6了. 但是, 从某种角度讲, 线程的执行效率真的就无敌了么? 我们真的充分的利用CPU资源了么? 非也~ 比如, 我们来看下面这个例子. 我们…...

visual studio code配置anaconda3的python虚拟环境

参考&#xff1a; Visual Studio Code配置anconda3虚拟环境 - 知乎...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)

旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据&#xff01;该数据集源自2025年4月发表于《地理学报》的论文成果…...

RabbitMQ 各类交换机

为什么要用交换机&#xff1f; 交换机用来路由消息。如果直发队列&#xff0c;这个消息就被处理消失了&#xff0c;那别的队列也需要这个消息怎么办&#xff1f;那就要用到交换机 交换机类型 1&#xff0c;fanout&#xff1a;广播 特点 广播所有消息​​&#xff1a;将消息…...

AT模式下的全局锁冲突如何解决?

一、全局锁冲突解决方案 1. 业务层重试机制&#xff08;推荐方案&#xff09; Service public class OrderService {GlobalTransactionalRetryable(maxAttempts 3, backoff Backoff(delay 100))public void createOrder(OrderDTO order) {// 库存扣减&#xff08;自动加全…...