当前位置: 首页 > 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虚拟环境 - 知乎...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...