☆★记录
再一次开发任务重,将数据库中的菜单信息给前端用来展示,前端希望得到的数据是一个带有层级结构的菜单列表。
故而写这篇笔记作为记录。
发现自己京常用的数据结构是列表、栈等,树是自己的弱项,找时间需要再恶补一下。
☆★注意事项
★数据结构特点:
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来获取当前父节点的孩子节点,当找到孩子时:
- 已经有孩子,获取孩子列表
- 无孩子,生成一个孩子列表
- 再去调用自身,获取孩子的孩子。
- 不断递归,每一次的递归会在当前传参的父节点无孩子时结束。
- 得到孩子对象(可能子孩子里面嵌套孩子),加入孩子列表。
- 更新孩子。
- 不断地遍历list来获取当前父节点的孩子节点,当找到孩子时:
☆★备注
这个方法主要是使用了树状结构的dfs(深度优先遍历),找时间使用bfs来解决此问题,并更新笔记。