使用Java流API构建树形结构数据

简介:

        在实际开发中,构建树状层次结构是常见需求,如组织架构、目录结构或菜单系统。本教案通过解析给定的Java代码,展示如何使用Java 8 Stream API将扁平化的菜单数据转换为具有层级关系的树形结构。

1. 核心类定义 - Menu

@Data
@NoArgsConstructor
@AllArgsConstructor
static class Menu {private Long id;private String name;private Long parentId;private List<Menu> children;
}

提示:此处定义了一个名为Menu的类,它包含了菜单项的基本属性,包括ID、名称、父菜单ID以及一个用于存储子菜单项的列表。

2. main方法解析及实现功能


输入参数:

  • List<Menu> menus:包含所有菜单项的集合。

输出结果:

  • List<Menu>:一个仅包含顶级菜单项的列表,每个顶级菜单项已填充了其下级子菜单。
public static void main(String[] args) {List<Menu> menus = menusData();/*** 从菜单列表中筛选出顶级菜单,并为其添加子菜单。** @param menus 菜单列表,包含所有菜单项。* @return 包含所有顶级菜单的列表,其中每个顶级菜单均已包含其所有子菜单。*/List<Menu> topLevelMenus = menus.stream() // 使用流处理menus集合.filter(menu -> menu.getParentId() == 0 || menus.stream().noneMatch(other -> other.getId().equals(menu.getParentId()))) // 筛选条件:父菜单ID为0或不存在对应父菜单的菜单项.peek(menu -> menu.setChildren(getChildren(menu, menus))) // 为每个顶级菜单设置子菜单.collect(Collectors.toList()); // 将筛选后的顶级菜单集合转换为List(Menu)类型}

 3. 辅助方法——获取指定菜单的所有子菜单

 /*** 获取指定菜单的所有子菜单。** @param menu 指定的菜单对象,我们要查找它的子菜单。* @param menus 所有菜单的列表,从中筛选出子菜单。* @return 返回一个包含指定菜单所有子菜单的列表。这个列表中的每个菜单对象都可能包含它们自己的子菜单列表。*/private static List<Menu> getChildren(Menu menu, List<Menu> menus) {// 使用流对菜单列表进行处理,筛选出指定菜单的子菜单return menus.stream().filter(child -> child.getParentId().equals(menu.getId())) // 筛选条件:菜单的父菜单ID与指定菜单ID匹配.peek(child -> child.setChildren(getChildren(child, menus))) // 递归设置每个子菜单的子菜单列表.collect(Collectors.toList()); // 收集结果,生成列表}

4. 示例数据生成方法 —— menusData()

private static List<Menu> menusData() {return Arrays.asList(new Menu(1L, "一级菜单1", 0L, null),new Menu(2L, "二级菜单1", 1L, null),new Menu(3L, "三级菜单1", 2L, null),new Menu(4L, "一级菜单2", 0L, null),new Menu(5L, "二级菜单2", 4L, null),new Menu(6L, "一级菜单3", 0L, null));
}

5.完整代码,以及演示(TreeExample.java)

package com.tenement.auto;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class TreeExample {@Data@NoArgsConstructor@AllArgsConstructorstaticclass Menu {private Long id;private String name;private Long parentId;private List<Menu> children;}public static void main(String[] args) {List<Menu> menus = menusData();/*** 从菜单列表中筛选出顶级菜单,并为其添加子菜单。** @param menus 菜单列表,包含所有菜单项。* @return 包含所有顶级菜单的列表,其中每个顶级菜单均已包含其所有子菜单。*/List<Menu> topLevelMenus = menus.stream() // 使用流处理menus集合.filter(menu -> menu.getParentId() == 0 || menus.stream().noneMatch(other -> other.getId().equals(menu.getParentId()))) // 筛选条件:父菜单ID为0或不存在对应父菜单的菜单项.peek(menu -> menu.setChildren(getChildren(menu, menus))) // 为每个顶级菜单设置子菜单.collect(Collectors.toList()); // 将筛选后的顶级菜单集合转换为List(Menu)类型}/*** 获取指定菜单的所有子菜单。** @param menu 指定的菜单对象,我们要查找它的子菜单。* @param menus 所有菜单的列表,从中筛选出子菜单。* @return 返回一个包含指定菜单所有子菜单的列表。这个列表中的每个菜单对象都可能包含它们自己的子菜单列表。*/private static List<Menu> getChildren(Menu menu, List<Menu> menus) {// 使用流对菜单列表进行处理,筛选出指定菜单的子菜单return menus.stream().filter(child -> child.getParentId().equals(menu.getId())) // 筛选条件:菜单的父菜单ID与指定菜单ID匹配.peek(child -> child.setChildren(getChildren(child, menus))) // 递归设置每个子菜单的子菜单列表.collect(Collectors.toList()); // 收集结果,生成列表}private static List<Menu> menusData() {return Arrays.asList(new Menu(1L, "一级菜单1", 0L,null),new Menu(2L, "二级菜单1", 1L,null),new Menu(3L, "三级菜单1", 2L,null),new Menu(4L, "一级菜单2", 0L,null),new Menu(5L, "二级菜单2", 4L,null),new Menu(6L, "一级菜单3", 0L,null));}}

总结:该案例展示了如何利用Java 的Stream API对菜单数据进行处理,首先筛选出顶级菜单项,并通过递归方式为其添加子菜单。最后,得到了一个完整的树形菜单结构。 

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

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

相关文章

【图论】【拓扑排序】1857. 有向图中最大颜色值

本文涉及的知识点 图论 拓扑排序 LeetCode1857. 有向图中最大颜色值 给你一个 有向图 &#xff0c;它含有 n 个节点和 m 条边。节点编号从 0 到 n - 1 。 给你一个字符串 colors &#xff0c;其中 colors[i] 是小写英文字母&#xff0c;表示图中第 i 个节点的 颜色 &#xf…

MySQL进阶-----SQL提示与覆盖索引

目录 前言 一、SQL提示 1.数据准备 2. SQL的自我选择 3.SQL提示 二、覆盖索引 前言 MySQL进阶篇的索引部分基本上要结束了&#xff0c;这里就剩下SQL提示、覆盖索引、前缀索引以及单例联合索引的内容。那本期的话我们就先讲解SQL提示和覆盖索引先&#xff0c;剩下的内容就…

HDU1020--编码问题

试题描述 问题详情如下图所示&#xff1a;要求&#xff1a;java实现、数据结构知识 参考代码 比较垃圾&#xff0c;在别人基础上改的&#xff0c;懒得重构&#xff0c;&#xff0c;&#xff0c;仅供参考 import java.util.Scanner;public class HDU1020StringEncoding {pu…

虚拟机安装银河麒麟

背景 由于Centos将于2024-06-30结束维护【脱保】&#xff0c;届时会存在Bug无人修复及功能无人开发等问题&#xff0c;所以要赶在这个节点前完成操作系统升级。可选的就是RedHat、Ubuntu以及国产信创【中标麒麟、银河麒麟、统信等】&#xff0c;或者使用云上操作系统【例如租阿…

【笔记】通过码云Gitee获取OpenHarmony源码

Note&#xff1a;下面包含操作过程和问题解决&#xff08;首次安装Ubuntu&#xff0c;环境未完善&#xff09;&#xff0c;没有遇到问题可以直接跳过问题part了&#xff0c;小白也能完成配置下载。 前置准备&#xff08;Git环境账号&#xff09; &#xff08;一&#xff09;安…

做抖店没有产品货源?怎么玩?筛选货源的方法你需要了解清楚!

大家好&#xff0c;我是电商小布。 有很多的新手朋友们在玩抖店的时候&#xff0c;遇到的第一个问题就是自己手里没有产品在。 没有产品货源&#xff0c;也就没办法上架店铺&#xff0c;更别提交易工作了。 那么在这种情况下&#xff0c;该怎么来玩呢&#xff1f; 既然我们…

设计模式——行为型——责任链模式Chain Of Responsibility

请求类 public class ApproverRequest {private int type;//请求批准的类型private float price;//请求的金额private int id;//请求的编号 } 审批人抽象类 public abstract class ApproverPerson {protected ApproverPerson next;protected String name;//审批过程public a…

跨境运营必看:TikTok账号防封指南

多人在使用TikTok的过程中都会遇到一些问题&#xff0c;比如为什么TikTok没有浏览量&#xff1f;事实上&#xff0c;这很可能是因为你的账号已被禁止。但为什么它会被封呢&#xff1f;你怎样才能解决它&#xff1f; 一、TikTok账号为什么被封&#xff1f; 1、什么是 TikTok 影…

【隐私计算实训营008——SCQL】

1.SCQL使用/集成最佳实践 目前SCQL只开放API供用户使用/集成 使用SCDBClient上手体验可以基于SCQL API开发封装白屏产品&#xff0c;或集成到业务链路中 1.1 部署系统 环境配置&#xff1a; 机器配置&#xff1a;CPU/MEM最低8C16G机构之间的网络互通 镜像&#xff1a;secret…

Flutter应用在苹果商店上架前的准备工作与注意事项

引言 &#x1f680; Flutter作为一种跨平台的移动应用程序开发框架&#xff0c;为开发者提供了便利&#xff0c;使他们能够通过单一的代码库构建出高性能、高保真度的应用程序&#xff0c;同时支持Android和iOS两个平台。然而&#xff0c;完成Flutter应用程序的开发只是第一步…

构建开源可观测平台

企业始终面临着确保 IT 基础设施和应用程序全年可用的压力。现代架构&#xff08;容器、混合云、SOA、微服务等&#xff09;的复杂性不断增长&#xff0c;产生大量难以管理的日志。我们需要智能应用程序性能管理 (APM) 和可观察性工具来实现卓越生产并满足可用性和正常运行时间…

算法错题本

这里写目录标题 错题本注意数据的耦合性对于无解情况的处理思路一组数据以0为结束标记&#xff0c;如何输入到数组中&#xff0c;并计数多个数据进行比较链表删除重复元素的启发循环体里谨慎写类型定义并初始化&#xff08;一般写上就是错&#xff09;队列中读取队尾元素数组当…

实现3D模型无变形的减面渲染方法---模大狮模型网

在进行3D模型渲染时&#xff0c;减面(或降面)是一种常用的优化技术&#xff0c;用于降低模型的复杂度&#xff0c;提高渲染效率。然而&#xff0c;在减面过程中&#xff0c;若不小心可能会引起模型的形变或细节丢失。模大狮将介绍一些方法和技巧&#xff0c;帮助您在减面渲染时…

安卓主板MT8390(Genio 700)_MTK联发科Linux开发板方案

MediaTek Genio 700 &#xff08;MT8390&#xff09;是一款高性能的边缘 AI 物联网平台&#xff0c;专为智能家居、互动零售、工业与商业应用而设计。提供快速响应的边缘计算能力、先进的多媒体功能、广泛的传感器和连接方式&#xff0c;且支持多任务操作系统。 MT8390安卓核心…

如何同时使用多个Gmail账号而不被关联?

您的业务活动需要多个 Gmail 帐户吗&#xff1f;出海畅游&#xff0c;Gmail账号是少不了的工具之一&#xff0c;可以关联到Twitter、Facebook、Youtube、Chatgpt等等平台&#xff0c;可以说是海外网络的“万能锁”。但是大家都知道&#xff0c;以上这些平台注册多账号如果产生关…

Linux:入门篇

文章目录 前言1. Linuxd的安装环境2.Linux的简单介绍2.1 新建目录2.2 新建文件 3.指令到底是什么&#xff1f;4.shell命令以及运行原理5.总结 前言 很多人对于Linux的学习总是感觉无法下手&#xff0c;不知道从何开始学习&#xff0c;相信这篇文章将会为你提供一个清晰的思路。…

【SpringBoot整合系列】SpirngBoot整合EasyExcel

目录 背景需求发展 EasyExcel官网介绍优势常用注解 SpringBoot整合EaxyExcel1.引入依赖2.实体类定义实体类代码示例注解解释 3.自定义转换器转换器代码示例涉及的枚举类型 4.Excel工具类5.简单导出接口SQL 6.简单导入接口SQL 7.复杂的导出&#xff08;合并行、合并列&#xff0…

mysql 本地电脑服务部署

前提&#xff1a; 下载mysql 新建配置文档 在安装mysql目录新建 my.ini [mysqld] # 设置3306端口 port3306#设置mysql的安装目录 basedirC:\Program Files\MySQL\MySQL Server 8.3 #切记此处一定要用双斜杠\\,单斜杠我这里会出错&#xff0c;不过看别人的教程&#xff0c;有…

Docker容器与虚拟化技术:OpenEuler 部署 Docker UI

目录 一、实验 1.环境 2.OpenEuler 部署 docker-compose-ui 2.OpenEuler 部署 docker ui 3.使用cpolar内网穿透 二、问题 1.docker run -w 的作用 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统架构版本IP备注LinuxopenEuler22.03 LTS SP2 192.168…

动态规划——计数类dp

例题&#xff1a;acwing900整数划分 完全背包解法 #include <iostream> #include <algorithm>using namespace std;const int N 1010, mod 1e9 7;int n; int f[N];int main() {cin >> n;f[0] 1;for (int i 1; i < n; i )for (int j i; j < n; …