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

简单封装一个类似菜单栏的树状结构转换

充血的菜单实体类

@Data
public class Menu {public Integer id;public String name;public Integer parentId;// 根节点为0public List<Menu> childList;public Menu(Integer id, String name, Integer parentId) {this.id = id;this.name = name;this.parentId = parentId;this.childList = new ArrayList<>();}public static List<Menu> selectAll() {return Arrays.asList(new Menu(1, "根节点", 0),new Menu(2, "子节点1", 1),new Menu(3, "子节点1.1", 2),new Menu(4, "子节点1.2", 2),new Menu(5, "根节点1.3", 2),new Menu(6, "根节点2", 1),new Menu(7, "根节点2.1", 6),new Menu(8, "根节点2.2", 6),new Menu(9, "根节点2.2.1", 7),new Menu(10, "根节点2.2.2", 7),new Menu(11, "根节点3", 1),new Menu(12, "根节点3.1", 11));}
}

先做实现

public class Test {public static void main(String[] args) {List<Menu> menuList = Menu.selectAll();// 1:遍历(O(n))节点并查找(O(1))加入父节点。总复杂度为O(n)。Map<Integer, Menu> menuMap = menuList.stream().collect(Collectors.toMap(Menu::getId, menu -> menu));menuMap.forEach((key, value) -> {if (value.getParentId() == 0) return; // 根节点不处理menuMap.get(value.getParentId()).getChildList().add(value);});Menu root = menuMap.get(1);System.out.println(root);}
}

封装一下,主要抽象了实体类的ID、父节点ID、子节点列表这三个字段的Getter

public class Test {public static void main(String[] args) {List<Menu> menuList = Menu.selectAll();// 抽象class Tree<T>{public T parse(List<T> list, Function<T, Integer> getId, Function<T,Integer> getParentId, Function<T, Collection<T>> getChildList) {Map<Integer, T> map = list.stream().collect(Collectors.toMap(getId, t -> t));map.forEach((key, value) -> {if (getParentId.apply(value) == 0) return; // 根节点不处理getChildList.apply(map.get(getParentId.apply(value))).add(value);});return map.get(1);}}Menu root = new Tree<Menu>().parse(menuList, Menu::getId, Menu::getParentId, Menu::getChildList);System.out.println(root);}
}

再封装一下,把根节点的判断条件封装了

public class Test {public static void main(String[] args) {List<Menu> menuList = Menu.selectAll();// 抽象class Tree<T>{public T parse(List<T> list, Function<T, Integer> getId, Function<T,Integer> getParentId, Function<T, Collection<T>> getChildList,Function<T,Boolean> isRoot) {AtomicReference<T> root = new AtomicReference<>();Map<Integer, T> map = list.stream().collect(Collectors.toMap(getId, t -> t));map.forEach((key, value) -> {if (isRoot.apply(value)) {root.set(value);return; // 根节点不处理}getChildList.apply(map.get(getParentId.apply(value))).add(value);});return root.get();}}Menu root = new Tree<Menu>().parse(menuList, Menu::getId, Menu::getParentId, Menu::getChildList, menu -> menu.getParentId() == 0);System.out.println(root);}
}

再再封装,类泛型有点大,改为方法泛型吧

public class Test {public static void main(String[] args) {List<Menu> menuList = Menu.selectAll();// 抽象class Tree {public static <T> T parse(List<T> list, Function<T, Integer> getId, Function<T,Integer> getParentId, Function<T, Collection<T>> getChildList,Function<T,Boolean> isRoot) {AtomicReference<T> root = new AtomicReference<>();Map<Integer, T> map = list.stream().collect(Collectors.toMap(getId, t -> t));map.forEach((key, value) -> {if (isRoot.apply(value)) {root.set(value);return; // 根节点不处理}getChildList.apply(map.get(getParentId.apply(value))).add(value);});return root.get();}}Menu root = Tree.parse(menuList, Menu::getId, Menu::getParentId, Menu::getChildList, menu -> menu.getParentId() == 0);System.out.println(root);}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • VMware-Ubuntu共享文件找不到
  • 深入探索分布式任务调度框架:MySQL实现高效锁机制
  • 误删?损坏?SD卡数据恢复全攻略,让你的数据起死回生!
  • RK3568平台(PWM篇)PWM驱动
  • xss-靶场
  • 基于协同过滤算法的体育商品推荐系统_t81xg
  • 气膜游泳馆:夏日避暑的绝佳选择—轻空间
  • Perl(Practical Extraction and Reporting Language)脚本
  • 自主身份:Web3如何重新定义个人数据所有权
  • 基于 Spring Boot 的快速开发微信公众平台的框架-FastBootWeixin框架
  • RabbitMQ-消息队列之topic使用
  • Linux目录结构及基础查看命令和命令模式
  • EmguCV学习笔记 VB.Net 4.5 像素距离和连通区域
  • ECCV2024|商汤发布3D面部动画系统UniTalker:通过统一模型扩展音频驱动的 3D 面部动画
  • Verilog刷题笔记55
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • C# 免费离线人脸识别 2.0 Demo
  • Computed property XXX was assigned to but it has no setter
  • happypack两次报错的问题
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • JS实现简单的MVC模式开发小游戏
  • Mac转Windows的拯救指南
  • magento 货币换算
  • Making An Indicator With Pure CSS
  • Map集合、散列表、红黑树介绍
  • Mocha测试初探
  • Webpack 4 学习01(基础配置)
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 关于字符编码你应该知道的事情
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 开发基于以太坊智能合约的DApp
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 中文输入法与React文本输入框的问题与解决方案
  • No resource identifier found for attribute,RxJava之zip操作符
  • k8s使用glusterfs实现动态持久化存储
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (03)光刻——半导体电路的绘制
  • (6)设计一个TimeMap
  • (LeetCode C++)盛最多水的容器
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (二十四)Flask之flask-session组件
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (十五)使用Nexus创建Maven私服
  • (四)库存超卖案例实战——优化redis分布式锁
  • (算法)区间调度问题
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)h264中avc和flv数据的解析
  • .chm格式文件如何阅读
  • .net core + vue 搭建前后端分离的框架
  • .net core 控制台应用程序读取配置文件app.config
  • .Net Core和.Net Standard直观理解
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .net 简单实现MD5
  • .NET 中创建支持集合初始化器的类型