含有父子结构的数据类型转化为层级列表

150 阅读2分钟

☆★记录

再一次开发任务重,将数据库中的菜单信息给前端用来展示,前端希望得到的数据是一个带有层级结构的菜单列表。

故而写这篇笔记作为记录。

发现自己京常用的数据结构是列表、栈等,树是自己的弱项,找时间需要再恶补一下。

☆★注意事项

★数据结构特点:

1、含有父节点

2、含有子节点的列表

3、如以下结构:

public class Menu {  
    private String id;  
    private String name;  
    private String fatherid;  
    private List<Menu> childList;  
    private String hasChildren;
}

4、该结构常用于以下场景:

  • 菜单
  • 嵌套对象

☆★代码

下面给出一块通用的代码,如上述对象Menu:

public List<Menu> getMenuTreeStyle() {  
    //获取对象列表
    List<Menu> menuList = menuMapper.getMenuTreeList();  
    List<Menu> resultList = new ArrayList<>();  
    List<String> idList = menuList.stream().map(Menu::getId).collect(Collectors.toList());  
    //设置最外层菜单  
    for (Menu tmpMenu: menuList){
        // 这里我定义的顶层结构的父节点为0
        if (tmpMenu.getFatherid().equals("0")){  
            resultList.add(tmpMenu);  
        }  
    }  
    for (Menu tmpMenu: resultList){  
        getChildren(menuList, tmpMenu);  
    }  
    return resultList;  
}  
  
public static Menu getChildren(List<Menu> list, Menu menu) {  
    for (Menu tmpMenu : list) {  
        if (menu.getId().equals(tmpMenu.getFatherid())) {  
            // ★最重要的逻辑
            List<Menu> children = CollectionUtil.isEmpty(menu.getChildList()) ? new ArrayList<>() : menu.getChildList();  
            children.add(getChildren(list, tmpMenu));  
            menu.setChildList(children);  
        }  
    }  
    return menu;  
}

★解读:

  • 首先将列表中的父亲节点提取出来,怎么提取按照自己设定父节点的特性来编码。
  • getChilden(列表,父节点)是一个递归函数
    • 不断地遍历list来获取当前父节点的孩子节点,当找到孩子时:
      • 已经有孩子,获取孩子列表
      • 无孩子,生成一个孩子列表
    • 再去调用自身,获取孩子的孩子。
    • 不断递归,每一次的递归会在当前传参的父节点无孩子时结束。
    • 得到孩子对象(可能子孩子里面嵌套孩子),加入孩子列表。
    • 更新孩子。

☆★备注

这个方法主要是使用了树状结构的dfs(深度优先遍历),找时间使用bfs来解决此问题,并更新笔记。