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

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...