• 摸鱼三天,我写了一个通用的组建树TreeUtil工具


    1. 树的简单遍历思路及写法

    ①数据准备

    Menu实体类

    1. /**
    2. * @date: 2022/7/25
    3. * @FileName: Menu
    4. * @author: Yan
    5. * @Des:
    6. */
    7. @Data
    8. @AllArgsConstructor
    9. @NoArgsConstructor
    10. public class Menu {
    11. private Integer id;
    12. private String name;
    13. private Integer parentId;
    14. private List children;
    15. public Menu(Integer id, String name, Integer parentId) {
    16. this.id = id;
    17. this.name = name;
    18. this.parentId = parentId;
    19. }
    20. }
    21. 复制代码

    创建测试数据List

    1. /**
    2. * @date: 2022/7/25
    3. * @FileName: TreeController
    4. * @author: Yan
    5. * @Des:
    6. */
    7. @RestController
    8. @RequestMapping("/tree")
    9. public class TreeController {
    10. public static List<Menu> getMenus(){
    11. List<Menu> menus = Arrays.asList(
    12. new Menu(1, "A公司", 0),
    13. new Menu(2, "a销售部", 14),
    14. new Menu(3, "财税部", 1),
    15. new Menu(4, "商务部", 1),
    16. new Menu(5, "综合部", 1),
    17. new Menu(6, "a销售1部", 2),
    18. new Menu(7, "a销售2部", 2),
    19. new Menu(8, "a销售3部", 2),
    20. new Menu(9, "a销售4部", 2),
    21. new Menu(10, "b销售部", 14),
    22. new Menu(11, "b销售1部", 10),
    23. new Menu(12, "b销售2部", 10),
    24. new Menu(13, "人事部", 1),
    25. new Menu(14, "销售部", 1));
    26. return menus;
    27. }
    28. }
    29. 复制代码

    ② 使用Lambda的语法糖遍历及制作树

    在TreeController中,写入:

    1. @RequestMapping
    2. public List<Menu> getTree(){
    3. List<Menu> menus = getMenus();
    4. List<Menu> menusTree = menus.stream()
    5. .filter(menu -> menu.getParentId() == 0)
    6. .map(menu -> {
    7. menu.setChildren(getChildrens(menu, menus));
    8. return menu;
    9. })
    10. .collect(Collectors.toList());
    11. return menusTree;
    12. }
    13. public static List<Menu> getChildrens(Menu root, List<Menu> allMenus){
    14. List<Menu> childrenTree = allMenus.stream()
    15. .filter(menu -> Objects.equals(menu.getParentId(), root.getId()))
    16. .peek(menu -> menu.setChildren(getChildrens(menu, allMenus)))
    17. .collect(Collectors.toList());
    18. return childrenTree;
    19. }
    20. 复制代码

    ③ 查看运行结果

    可以看到,我们成功的返回了树形结构

     

    问题的出现

    最近看公司项目,经常会碰到一些场景是需要以树形结构展示的,比如说部门树,设备树,分类树等等,但是感觉好像都是需要用到的时候现写的,但是大体的思路是一样的,感觉重复写就有点冗余了,而且对应的树形结构构建又相对麻烦,我就想着抽离一下,做成一个通用的工具类TreeUtil,于是翻了一下别的大佬的文章,学着写了这样的一个工具类。

    问题的解决

    2. 制作工具

    2.1 TreeNode接口

    TreeNode用来表示每个树节点的抽象,即需要生成树的对象需要实现此接口。

    1. /**
    2. * @date: 2022/7/25
    3. * @FileName: TreeNode
    4. * @author: Yan
    5. * @Des: 树节点父类,所有需要使用TreeUtils工具类形成树形结构等操作的节点都需要实现该接口
    6. */
    7. public interface TreeNode<T, RC, LC> {
    8. /**
    9. * 获取树结点id
    10. * @return
    11. */
    12. T getTreeNodeId();
    13. /**
    14. * 获取该节点的父节点id
    15. * @return
    16. */
    17. T getParentId();
    18. /**
    19. * 判断该节点是否为根节点,默认判定
    20. * @Des 可以用于简单树的组件
    21. * @return
    22. */
    23. boolean isRoot();
    24. /**
    25. * 自定义父结点的判定规则
    26. * @param rootCondition
    27. * @return
    28. */
    29. boolean isRoot(RC rootCondition);
    30. /**
    31. * 自定义子节点(叶子结点)的判定规则
    32. * @param leafCondition
    33. * @return
    34. */
    35. boolean isChildren(LC leafCondition);
    36. /**
    37. * 判断是否有子节点
    38. * @return
    39. */
    40. boolean hasChild();
    41. /**
    42. * 设置结点的子节点列表
    43. * @param children
    44. */
    45. void setChildren(List<? extends TreeNode<T, RC, LC>> children);
    46. /**
    47. * 获取所有子节点
    48. * @return
    49. */
    50. List<? extends TreeNode<T, RC, LC>> getChildren();
    51. /**
    52. * 获取树的深度
    53. * @return
    54. */
    55. Integer getLevel();
    56. /**
    57. * 设置树的深度
    58. */
    59. void setLevel(Integer level);
    60. }
    61. 复制代码

    泛型说明:

    T 主要定义返回值的类型

    RC(rootCondition) 主要是定义根节点 (也就是父节点) 的自定义判定规则需要用到的参数类型

    LC(leafCondition) 主要是定义叶子结点(也就是子节点)的自定义判定规则需要用到的参数类型

    2.2 TreeUtil工具类


    回调函数——函数式接口

    用于遍历树作自定义操作使用

    1. /**
    2. * @date: 2022/7/28
    3. * @FileName: Handle
    4. * @author: Yan
    5. * @Des: 定义一个函数式接口
    6. */
    7. @FunctionalInterface
    8. public interface FunctionHandle <N, K, V> {
    9. void
  • 相关阅读:
    概率论的学习和整理--番外4: 关于各种平均数:算术平均数,几何平均数,调和平均数,以及加权平均数和平方平均数 (未完成)
    剑指offer 15. 数值的整数次方
    C++ PrimerPlus 复习 第二章 进入c++
    靠着腾讯的「操作系统笔记」,成功帮我拿下了 3 个大厂的 offer
    Jackson 工具类
    20、架构-容器间网络
    React报错之Style prop value must be an object
    灰色关联分析(Grey Relational Analysis, GRA)
    图文并茂使用VUE+Quasar CLI开发和构建PWA
    飞书中板栗看板适合做复杂任务管理吗
  • 原文地址:https://blog.csdn.net/Cr1556648487/article/details/126604844