递归遍历菜单树(java8)

5 篇文章 0 订阅

实体类

package org.example;

import lombok.Data;

import java.util.List;

@Data
public class Menu {
    /**
     * id
     */
    private String id;

    /**
     * 菜单名称
     */
    private String name;

    /**
     * 父节点id
     */
    private String pid;

    /**
     * 子节点
     */
    private List<Menu> children;

    /**
     * 带参构造
     */
    public Menu(String id, String name, String pid) {
        this.id = id;
        this.name = name;
        this.pid = pid;
    }
}

1.遍历属性结构(多个根节点)

package org.example;


import com.alibaba.fastjson2.JSONObject;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class App {
    public static void main(String[] args) {
        //模拟数据库查出所有数据(多个根节点)
        List<Menu> menus = Arrays.asList(
                new Menu("1", "根节点1", "0"),
                new Menu("2", "子节点1-1", "1"),
                new Menu("3", "子子节点1-1-1", "2"),
                new Menu("4", "子子子节点1-1-1-1", "3"),
                new Menu("5", "子节点1-2", "1"),
                new Menu("6", "子子节点1-2-1", "5"),
                new Menu("7", "根节点2", "0"),
                new Menu("8", "子节点2-1", "7"),
                new Menu("9", "子子节点2-1-1", "8")
        );
        List<Menu> tree = getTree(menus);
        System.out.println(JSONObject.toJSONString(tree));
    }

    /**
     * 遍历树(多个根节点)
     *
     * @param menus
     */
    public static List<Menu> getTree(List<Menu> menus) {
        // 筛选出根节点
        return menus.stream().filter(m -> Objects.equals(m.getPid(), "0")).map(m ->
        {
            //设置每个树的子节点
            m.setChildren(getChildrens(m, menus));
            return m;
        }).collect(Collectors.toList());
    }

    /**
     * 获取子节点
     *
     * @param root
     * @param menus
     * @return
     */
    public static List<Menu> getChildrens(Menu root, List<Menu> menus) {
        //筛选直接子节点
        return menus.stream().filter(m -> Objects.equals(m.getPid(), root.getId())).map(
                m -> {
                    // 递归设置子节点
                    m.setChildren(getChildrens(m, menus));
                    return m;
                }
        ).collect(Collectors.toList());
    }
}

输出:

[{"children":[{"children":[{"children":[{"children":[],"id":"4","name":"子子子节点1-1-1-1","pid":"3"}],"id":"3","name":"子子节点1-1-1","pid":"2"}],"id":"2","name":"子节点1-1","pid":"1"},{"children":[{"children":[],"id":"6","name":"子子节点1-2-1","pid":"5"}],"id":"5","name":"子节点1-2","pid":"1"}],"id":"1","name":"根节点1","pid":"0"},{"children":[{"children":[{"children":[],"id":"9","name":"子子节点2-1-1","pid":"8"}],"id":"8","name":"子节点2-1","pid":"7"}],"id":"7","name":"根节点2","pid":"0"}]

2.获取节点路径path

一般新增节点时将节点路径存入数据库,便于查看从根节点到子节点的路径

    /**
     * 获取节点路径
     *
     * @param id  要计算的节点id
     * @param map
     * @return
     */
    public static String getPath(String id, Map<String, String> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        List<String> pathList = new ArrayList<>();
        // 构建路径
        buildPath(id, map, pathList);
        // 翻转
        Collections.reverse(pathList);
        return StringUtils.join(pathList, ",");
    }

    /**
     * 构建路径
     *
     * @param id       节点id
     * @param map
     * @param pathList 路径
     */
    public static void buildPath(String id, Map<String, String> map, List<String> pathList) {
        if (Objects.isNull(id) || Objects.equals(id, "0")) {
            return;
        }
        pathList.add(id);
        String pid = map.get(id);
        buildPath(pid, map, pathList);
    }

测试:

    public static void main(String[] args) {
        //模拟数据库查出所有数据(多个根节点)
        List<Menu> menus = Arrays.asList(
                new Menu("1", "根节点1", "0"),
                new Menu("2", "子节点1-1", "1"),
                new Menu("3", "子子节点1-1-1", "2"),
                new Menu("4", "子子子节点1-1-1-1", "3"),
                new Menu("5", "子节点1-2", "1"),
                new Menu("6", "子子节点1-2-1", "5"),
                new Menu("7", "根节点2", "0"),
                new Menu("8", "子节点2-1", "7"),
                new Menu("9", "子子节点2-1-1", "8")
        );
        // 模拟从数据库查询出父子关系
        Map<String, String> map = menus.stream().collect(Collectors.toMap(Menu::getId,
                Menu::getPid));
        System.out.println(getPath("1", map));  // 1
        System.out.println(getPath("3", map));  // 1,2,3
        System.out.println(getPath("9", map));  // 7,8,9
    }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值