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

2024-08-21 14:36

本文主要是介绍简单封装一个类似菜单栏的树状结构转换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

充血的菜单实体类

@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);}
}

这篇关于简单封装一个类似菜单栏的树状结构转换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093439

相关文章

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

uva 10387 Billiard(简单几何)

题意是一个球从矩形的中点出发,告诉你小球与矩形两条边的碰撞次数与小球回到原点的时间,求小球出发时的角度和小球的速度。 简单的几何问题,小球每与竖边碰撞一次,向右扩展一个相同的矩形;每与横边碰撞一次,向上扩展一个相同的矩形。 可以发现,扩展矩形的路径和在当前矩形中的每一段路径相同,当小球回到出发点时,一条直线的路径刚好经过最后一个扩展矩形的中心点。 最后扩展的路径和横边竖边恰好组成一个直

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 10130 简单背包

题意: 背包和 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

JavaSE——封装、继承和多态

1. 封装 1.1 概念      面向对象程序三大特性:封装、继承、多态 。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节 。     比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器, USB 插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU 、显卡、内存等一些硬件元件。