菜单树
业务中有很多时候需要用到菜单树的结构,比如菜单、评论系统等
菜单树
菜单树的实现分析
1.递归
菜单树的实现最原始的方法就是递归实现
数据量不是很到大的时候可以采用一次性将数据读取出存到list集合中,然后对该集合进行遍历。
/**
* 根据父节点的ID获取所有子节点
*
* @param list 分类表
* @param parentId 传入的父节点ID
* @return String
*/
public List<Menu> getChildPerms(List<Menu> list, Long parentId) {
List<Menu> returnList = new ArrayList<Menu>();
list.stream().forEach(menu -> {
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
if (menu.getPId().equals(parentId)) {
recursionFn(list, menu);
returnList.add(menu);
}
});
return returnList;
}
/**
* 递归列表
*
* @param list
* @param t
*/
private void recursionFn(List<Menu> list, Menu t) {
// 得到子节点列表
List<Menu> childList = getChildList(list, t);
t.setChildren(childList);
childList.stream().forEach(tChild -> {
if (hasChild(list, tChild)) {
recursionFn(list, tChild);
}
});
}
/**
* 得到子节点列表
*/
private List<Menu> getChildList(List<Menu> list, Menu t) {
List<Menu> tlist = new ArrayList<Menu>();
list.stream().filter(menu -> menu.getPId().equals(t.getId())).forEach(menu -> {
tlist.add(menu);
});
return tlist;
}
/**
* 判断是否有子节点
*/
private boolean hasChild(List<Menu> list, Menu t) {
return getChildList(list, t).size() > 0 ? true : false;
}
2.生成树实现
思想: 自己查百度生成树的思想,只有将思想弄明白之后才能实现需求
实现思路:
- 首先将获得的list集合转成map集合 ;
- 遍历list集合
- 如果是根节点则直接存储到treelist中;
- 如果是非根节点,则找到当前对象的父级对象,将其添加到父级节点的child中报存;
时间复杂度O(N);
/** * <p> * 根据生成树的思想构建菜单树 * * </P> * * @param list: 数据库获取符合条件的菜单列表 * @author: zhang.rongjun * @DateTime: 8/9/2021 9:11 AM * @return 菜单树 */ @Override public List<Menu> getTreeByColl(List<Menu> list) { Map<Long, Menu> map; List<Menu> treelist = new ArrayList<>(); if (null == list || list.isEmpty()) { return null; } //toMap()的第一个参数就是用来生成key值的,第二个参数就是用来生成value值的。 //第三个参数用在key值冲突的情况下:如果新元素产生的key在Map中已经出现过了,第三个参数就会定义解决的办法。 //如果k1与k2的key值相同,选择k1作为那个key所对应的value值。 map = list.stream().collect(Collectors.toMap(Menu::getId, a -> a, (k1, k2) -> k1)); // 将list集合对象转换为json的字符串 // 如果id是父级的话就放入tree中treelist list.forEach(menu -> { // 获取父级目录 if (map.get(menu.getPId()).equals(0L)) { treelist.add(menu); } else { // 子级通过父id获取到父级的类型 Menu parent = map.get(menu.getPId()); // 父级获得子级,再将子级放到对应的父级中 parent.getChildren().add(menu); } }); return treelist; }
拓展 二叉树的路径遍历
/**
* 257. 二叉树的所有路径
*/
List<String> pathList = new ArrayList<>();
public List<String> binaryTreePaths(TreeNode root) {
getPathsDfs(root, "");
return pathList;
}
private void getPathsDfs(TreeNode root, String pre){
if (root == null){
return;
}
if (root.left == null && root.right == null){
pathList.add(pre + root.val);
}
String str = pre + "->" + root.val;
getPathsDfs(root.left, str);
getPathsDfs(root.right, str);
}