Javai递归实现遍历父子级菜单

目录

准备工作

递归实现

未带有显示顺序的递归遍历

准备工作

create table dormitory_management.fuzi
(menu_id       bigint auto_increment comment '菜单ID'primary key,menu_name     varchar(50)      not null comment '菜单名称',parent_id     bigint default 0 null comment '父菜单ID',display_order int    default 0 null comment '显示顺序'
);-- 添加中文测试数据
INSERT INTO dormitory_management.fuzi (menu_name, parent_id, display_order) VALUES
('顶级菜单1', 0, 1),
('顶级菜单2', 0, 2),
('子菜单1-1', 1, 1),
('子菜单1-2', 1, 2),
('子菜单2-1', 2, 1);
@Data
@ToString
public class Fuzi {private Long menuId;private String menuName;private Long parentId;private Long  displayOrder;private List<Fuzi> children; // 子菜单列表
}

递归实现


//Service层
public interface FuziService extends IService<Fuzi> {List<Fuzi> getFuziMenuTreeWithoutChildren();List<Fuzi> buildMenuTree(List<Fuzi> menuList);
}
package com.lyh.mp.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyh.mp.entity.Fuzi;
import com.lyh.mp.mapper.FuziMapper;
import com.lyh.mp.service.FuziService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.*;/*** @author Mtz* @version 1.0* @2024/2/2015:49* @function* @comment*/
@Service
public class FuziServiceImpl extends ServiceImpl<FuziMapper, Fuzi> implements FuziService {@Autowiredprivate FuziMapper fuziMapper;public List<Fuzi> getFuziMenuTreeWithoutChildren() {QueryWrapper<Fuzi> fuzi = new QueryWrapper<>();fuzi.select("menu_id", "menu_name", "parent_id","display_order"); // 指定查询的字段List<Fuzi> menuList = fuziMapper.selectList(fuzi);return buildMenuTree(menuList); // 构建菜单树}// 构建父子级菜单树public List<Fuzi> buildMenuTree(List<Fuzi> menuList) {Map<Long, Fuzi> menuMap = new HashMap<>();// 将菜单放入Map中,以菜单ID作为键for (Fuzi menu : menuList) {menuMap.put(menu.getMenuId(), menu);}// 遍历菜单列表,将子菜单添加到对应的父菜单的children属性中List<Fuzi> treeMenu = new ArrayList<>();for (Fuzi menu : menuList) {Long parentId = menu.getParentId();if (parentId == null || parentId == 0) {// 顶级菜单treeMenu.add(menu);} else {// 子菜单Fuzi parentMenu = menuMap.get(parentId);if (parentMenu != null) {if (parentMenu.getChildren() == null) {parentMenu.setChildren(new ArrayList<>());}parentMenu.getChildren().add(menu);}}}// 对顶级菜单及其子菜单按照 display_order 排序sortTreeMenu(treeMenu);return treeMenu;}// 递归排序树形结构的菜单private void sortTreeMenu(List<Fuzi> treeMenu) {for (Fuzi menu : treeMenu) {if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {// 递归排序子菜单sortTreeMenu(menu.getChildren());}}// 对当前层级的菜单按照 display_order 排序Collections.sort(treeMenu, Comparator.comparingLong(Fuzi::getDisplayOrder));}/*- Fuzi(menuId=1, menuName=顶级菜单1, parentId=0, displayOrder=1, children=[- Fuzi(menuId=3, menuName=子菜单1-1, parentId=1, displayOrder=1, children=null),- Fuzi(menuId=4, menuName=子菜单1-2, parentId=1, displayOrder=2, children=null)])- Fuzi(menuId=2, menuName=顶级菜单2, parentId=0, displayOrder=2, children=[- Fuzi(menuId=5, menuName=子菜单2-1, parentId=2, displayOrder=1, children=null)])*/
}

未带有显示顺序的递归遍历

    public List<Fuzi> getFuziMenuTreeWithoutChildren() {QueryWrapper<Fuzi> fuzi = new QueryWrapper<>();fuzi.select("menu_id", "menu_name", "parent_id"); // 指定查询的字段List<Fuzi> menuList = fuziMapper.selectList(fuzi);return buildMenuTree(menuList); // 构建菜单树}// 构建父子级菜单树public List<Fuzi> buildMenuTree(List<Fuzi> menuList) {Map<Long, Fuzi> menuMap = new HashMap<>();// 将菜单放入Map中,以菜单ID作为键for (Fuzi menu : menuList) {menuMap.put(menu.getMenuId(), menu);}System.out.println(menuMap);// 遍历菜单列表,将子菜单添加到对应的父菜单的children属性中List<Fuzi> treeMenu = new ArrayList<>();for (Fuzi menu : menuList) {Long parentId = menu.getParentId();if (parentId == null || parentId == 0) {// 顶级菜单treeMenu.add(menu);} else {// 子菜单Fuzi parentMenu = menuMap.get(parentId);if (parentMenu != null) {if (parentMenu.getChildren() == null) {parentMenu.setChildren(new ArrayList<>());}parentMenu.getChildren().add(menu);}}}return treeMenu;}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在UE5中使用OverlayMaterial制作多材质效果

UE5.1中新增了OverlayMaterial&#xff0c;可以让物体套用2个材质球效果&#xff0c;如A材质球为正常材质内容&#xff0c;B材质球为菲涅尔&#xff0c;或是B材质球是法线外拓描边等&#xff0c;该功能类似Unity的多pass效果&#xff0c;方便了日常使用。 下面就讲将怎么用Ove…

开源软件的利弊

目录 开源软件 优势 免费 透明 可更改 可协作 影响力 坏处 安全隐患 良莠不齐 学习成本 持续性问题 未知风险 开源软件 开源软件是一种基于开放协作和共享的软件开发模式&#xff0c;其利弊对于软件产业和社会发展具有重要意义 优势 免费 谁能拒绝不要钱的东西…

如何接口调优?

接口调优是一个涉及多个方面的过程&#xff0c;旨在提高接口的性能、稳定性和可伸缩性。下面是一些常见的接口调优建议&#xff1a; 性能分析&#xff1a; 使用性能分析工具&#xff08;如Profiler、JMeter、LoadRunner等&#xff09;对接口进行压力测试和性能分析&#xff0c;…

多线程相关(1)

线程调度 线程状态&#xff1a;状态切换阻塞与唤醒阻塞唤醒 wait 与 sleep创建线程方式 线程是cpu任务调度的最小执行单位&#xff0c;每个线程拥有自己独立的程序计数器、虚拟机栈、本地方法栈。 线程状态&#xff1a; 线程状态包括&#xff1a;创建、就绪、运行、阻塞、死亡…

2024.2.20

使用多进程完成两个文件的拷贝&#xff0c;父进程拷贝前一半&#xff0c;子进程拷贝后一半&#xff0c;父进程回收子进程的资源 #include<myhead.h> int main(int argc, const char *argv[]) {char str[100]"";puts("please input str:");//从终端读…

深入剖析Nginx:技术解析、最佳实践和高级使用指南(二)

本系列文章简介: 本系列文章通过分析Nginx的内部机制和原理,讲解了Nginx的架构、性能优化和高可用性配置等方面的知识。此外,还介绍了Nginx的最佳实践和高级使用技巧,帮助读者更好地理解和应用Nginx。本系列文章内容详实且深入,适合对Nginx感兴趣的开发人员、系统管理员和…

软件实例分享,饭店餐饮会员卡管理系统怎么弄会员充值怎么记账

软件实例分享&#xff0c;饭店餐饮会员卡管理系统怎么弄会员充值怎么记账 一、前言 以下软件教程以 佳易王餐饮会员管理系统软件V16为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、会员可以登记电子会员卡或使用vip卡片 2、卡类型可以自由…

单片机技术的未来发展趋势:人工智能与物联网的融合

单片机技术在未来的发展趋势中&#xff0c;人工智能&#xff08;AI&#xff09;和物联网&#xff08;IoT&#xff09;的融合将会是一个重要的方向。以下是关于单片机技术未来发展趋势中人工智能与物联网融合的几个小点&#xff1a; 1.智能化设备和系统&#xff1a; 随着人工智…

从零学算法322

322.给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。 你可以认为每种硬币的数量是无限的。 …

【LeetCode】无权图的最短路精选7题——单源、多源

目录 无权图的单源最短路问题&#xff1a; 1. 迷宫中离入口最近的出口&#xff08;中等&#xff09; 2. 最小基因变化&#xff08;中等&#xff09; 3. 单词接龙&#xff08;困难&#xff09; 4. 为高尔夫比赛砍树&#xff08;困难&#xff09; 无权图的多源最短路问题&a…

疾控中心污水采样过程中会遇到哪些困难

在疾控中心的污水采样过程中&#xff0c;可能会遇到多种困难。 首先&#xff0c;污水的成分可能非常复杂&#xff0c;包括各种细菌、病毒、寄生虫、重金属、化学物质等&#xff0c;这给采样带来了很大的挑战。其次&#xff0c;污水中的有害物质可能会对采样设备和人员造成损害…

嘎嘎嘎嘎嘎嘎嘎

☞ 通用计算机启动过程 1️⃣一个基础固件&#xff1a;BIOS 一个基础固件&#xff1a;BIOS→基本IO系统&#xff0c;它提供以下功能&#xff1a; 上电后自检功能 Power-On Self-Test&#xff0c;即POST&#xff1a;上电后&#xff0c;识别硬件配置并对其进行自检&#xff0c…

预处理详解

目录 预定义符号介绍 ​编辑 预处理指令 #define #define 定义标识符 #define 定义宏 #define 替换规则 #define中#和##的使用 带副作用的宏参数 宏和函数的对比 命令行定义 预处理指令 #undef 预处理指令 #include 头文件被包含的方式&#xff1a; 本地文件包含 …

【LeetCode-139】单词拆分(回溯动归)

目录 题目描述 解法1&#xff1a;记忆回溯 代码实现 解法2&#xff1a;动态规划 代码实现 题目链接 题目描述 给定一个非空字符串 s 和一个包含非空单词的列表 wordDict&#xff0c;判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。 说明&#xff1a; 拆分…

Mybatis的一些工具类

** 1.实现了Interceptor接口&#xff0c;并实现了两个拦截方法&#xff1a;update和query。当Mybatis执行update或query语句时&#xff0c;会自动调用intercept法。intercept方法首先获取当前执行的SQL语句&#xff0c;并计算执行该SQL语句所需的时间。然后&#xff0c;它将执行…

【Unity】【VR开发】Unity云同步功能使用心得

【背景】 有时出差,旅行等等也带着电脑,晚上想要继续编辑项目,就需要用到云同步功能。目前实践下来,发现有些内容可以同步,有些内容则是不可以同步的,总结如下。 【如何云同步一个本地项目】 UnityHub的项目面板中有两个选项卡:项目和云端项目。 鼠标挪动到想要云同步…

c++类和对象新手保姆级上手教学(中)

前言&#xff1a; 类和对象中篇&#xff0c;这里讲到的前4个默认成员函数&#xff0c;是类和对象中的重难点&#xff0c;许多资料上的讲法都非常抽象&#xff0c;难以理解&#xff0c;所以我作出这篇总结&#xff0c;分享学习经验&#xff0c;以便日后复习。 目录 6个默认成员…

土壤墒情监测站的工作原理

TH-TS600土壤墒情自动监测站是一种用于自动检测土壤墒情的仪器&#xff0c;它可以实时监测土壤的水分含量和温度&#xff0c;并将数据传输到数据中心或监测中心进行分析和处理。 土壤墒情自动监测站通常由传感器、数据采集器、数据传输设备和数据处理软件等部分组成。传感器是…

Laravel02 路由基本概念和用法 给视图传递请求参数

Laravel02 路由基本概念和用法 1. 路由的基本概念2. 给视图传递请求参数 1. 路由的基本概念 routes文件夹下的web.php是用来定义路由规则的。 自己定义一个路径 2. 给视图传递请求参数 在laravel里使用一个辅助函数request来快速获取请求参数

NX/UG二次开发—CAM—平面铣边界准确设置方法

大家在对平面铣设置边界时&#xff0c;经常遇到边界方向与自己期望的不一致&#xff0c;有些人喜欢用检查刀路是否过切来判断&#xff0c;但是对于倒角、负余量等一些情况&#xff0c;刀路本来就是过切的。对于多边界&#xff0c;可以根据选择的曲线来起点和面的方向来确定&…