使用 stream 流构建树(不使用递归)

你知道的越多,你不知道的越多
点赞再看,养成习惯
如果您有疑问或者见解,欢迎指教:
企鹅:869192208

前言

最近遇到一个地区数据需要转换成树的需求,研究了一种新方法,不使用传统递归的方式,而是使用 stream 流的方式构建树。

代码实现
定义测试实体类
import lombok.Data;
import java.util.List;

/**
 * <h2> </h2>
 *
 * @author xymy
 * @date 2023/12/21 17:17
 */
@Data
public class TsModel {
    private String id;
    private String name;
    private String pid;
    private List<TsModel> childs;
}
实现方法
public static void main(String[] args) {
        String str = "[\n" +
                "    {\"id\":\"1\",\"name\":\"张三\",\"pid\":\"\"},\n" +
                "    {\"id\":\"2\",\"name\":\"张三2\",\"pid\":\"\"},\n" +
                "    {\"id\":\"3\",\"name\":\"张三3\",\"pid\":\"\"},\n" +
                "    {\"id\":\"4\",\"name\":\"张三4\",\"pid\":\"\"},\n" +
                "    {\"id\":\"33\",\"name\":\"张三33\",\"pid\":\"3\"},\n" +
                "    {\"id\":\"330\",\"name\":\"张三330\",\"pid\":\"3\"},\n" +
                "    {\"id\":\"3301\",\"name\":\"张三330\",\"pid\":\"330\"},\n" +
                "    {\"id\":\"41\",\"name\":\"张三41\",\"pid\":\"4\"}\n" +
                "]";
        List<TsModel> tsModels = JSONArray.parseArray(str, TsModel.class);
        Map<String, List<TsModel>> pModels = tsModels.stream().collect(Collectors.groupingBy(ts -> StringUtils.isBlank(ts.getPid()) ? "" : ts.getPid()));

        List<TsModel> childTs = new ArrayList<>();
        for (TsModel tsModel : tsModels) {
            String id = tsModel.getId();
            List<TsModel> childModel = pModels.get(id);
            if (CollectionUtils.isNotEmpty(childModel)) {
                tsModel.setChilds(childModel);
                childTs.addAll(childModel);
            }
        }
        Set<String> childSeqs = childTs.stream().map(t -> t.getId()).collect(Collectors.toSet());
        List<TsModel> newTree = tsModels.stream().filter(tsm -> !childSeqs.contains(tsm.getId())).collect(Collectors.toList());

        System.out.println(JSON.toJSONString(newTree));
    }

打印结果:

[
    {
        "id": "1",
        "name": "张三",
        "pid": ""
    },
    {
        "id": "2",
        "name": "张三2",
        "pid": ""
    },
    {
        "childs": [
            {
                "id": "33",
                "name": "张三33",
                "pid": "3"
            },
            {
                "childs": [
                    {
                        "id": "3301",
                        "name": "张三330",
                        "pid": "330"
                    }
                ],
                "id": "330",
                "name": "张三330",
                "pid": "3"
            }
        ],
        "id": "3",
        "name": "张三3",
        "pid": ""
    },
    {
        "childs": [
            {
                "id": "41",
                "name": "张三41",
                "pid": "4"
            }
        ],
        "id": "4",
        "name": "张三4",
        "pid": ""
    }
]

至此,就实现了列表转成树的逻辑。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Lambda表达式可以简化Java代码,并且可以使代码更加易读和易于维护。下面以Java 8为例,演示如何使用Lambda表达式查询菜单表: ```java import java.sql.*; import java.util.ArrayList; import java.util.List; public class MenuTree { public static void main(String[] args) { try { // 连接数据库 Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password"); // 执行查询语句,并使用Lambda表达式对ResultSet进行处理 List<Menu> menus = new ArrayList<>(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT id, name, ParentId, delectableflag FROM menu"); while (rs.next()) { Menu menu = new Menu( rs.getInt("id"), rs.getString("name"), rs.getInt("ParentId"), rs.getBoolean("delectableflag") ); menus.add(menu); } // 关闭连接 rs.close(); stmt.close(); conn.close(); // 根据菜单项构建菜单使用Lambda表达式进行递归 List<Menu> menuTree = buildMenuTree(menus, 0); menuTree.forEach(Menu::print); } catch (Exception e) { e.printStackTrace(); } } private static List<Menu> buildMenuTree(List<Menu> menus, int parentId) { List<Menu> result = new ArrayList<>(); menus.stream() .filter(menu -> menu.getParentId() == parentId) .forEach(menu -> { List<Menu> children = buildMenuTree(menus, menu.getId()); menu.setChildren(children); result.add(menu); }); return result; } } class Menu { private int id; private String name; private int parentId; private boolean delectableflag; private List<Menu> children; public Menu(int id, String name, int parentId, boolean delectableflag) { this.id = id; this.name = name; this.parentId = parentId; this.delectableflag = delectableflag; } public int getId() { return id; } public String getName() { return name; } public int getParentId() { return parentId; } public boolean isDelectable() { return delectableflag; } public List<Menu> getChildren() { return children; } public void setChildren(List<Menu> children) { this.children = children; } public void print() { print(0); } private void print(int level) { System.out.println(String.format("%s%s (%d)", " ".repeat(level * 2), name, id)); if (children != null) { for (Menu child : children) { child.print(level + 1); } } } } ``` 以上代码中,使用Lambda表达式对ResultSet进行处理,将每个菜单项构建成Menu对象,并将它们添加到列表中。然后,使用Lambda表达式对列表进行递归,根据每个菜单项的parentId构建菜单。最后,使用Lambda表达式输出菜单

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值