通过Java的Stream流将List转为树形结构

it2026-01-07  7

前言

日常开发中可能会遇到一些需求,比如构建菜单,构建树形结构,数据库一般就使用父id来表示,为了降低数据库的查询压力,我们可以使用Java8中的Stream流一次性把数据查出来,然后通过流式处理,转为树形结构。下面我们一起来看看怎么做。

1. 首先数据库菜单资源表数据如下:

2. SysMenuMapper.xml中SQL如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.pfms.master.mapper.SysMenuMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.pfms.master.entity.SysMenu"> <id column="ID" property="id" /> <result column="URL" property="url" /> <result column="PATH" property="path" /> <result column="COMPONENT" property="component" /> <result column="NAME" property="name" /> <result column="ICON" property="icon" /> <result column="PARENT_ID" property="parentId" /> <result column="KEEP_ALIVE" property="keepAlive" /> <result column="REQUIRE_AUTH" property="requireAuth" /> <result column="ENABLED" property="enabled" /> <result column="REMARK" property="remark" /> <result column="CREATE_BY" property="createBy" /> <result column="CREATE_DATE" property="createDate" /> <result column="UPDATE_BY" property="updateBy" /> <result column="UPDATE_DATE" property="updateDate" /> <!--assocication可以指定联合的JavaBean对象, property="role"指定哪个属性是联合的对象, javaType:指定这个属性对象的类型--> <association property="meta" javaType="com.pfms.master.entity.domain.Meta"> <result column="keepAlive" property="keepAlive"/> <result column="requireAuth" property="requireAuth"/> </association> </resultMap> <select id="getMenusByUserId_" resultMap="BaseResultMap"> SELECT * FROM `sys_menu` WHERE ID IN ( SELECT MENU_ID FROM sys_menu_role WHERE ROLE_ID IN ( SELECT ROLE_ID FROM sys_user_role WHERE USER_ID = #{userId} ) ) AND PATH IS NOT NULL AND PATH != '' ORDER BY ID </select> </mapper>
3. 主要代码
/* 另一种形式 */ List<SysMenu> menus = baseMapper.getMenusByUserId_(userId); if (isNotEmpty(menus)) { // 递归获取菜单树形结构 // 获取父节点,说明:父节点的parentId都是1(根节点是0) resultMenus = menus.stream().filter(m -> m.getParentId() == 1).peek( (m) -> m.setChildren(getChildren(m, menus)) ).collect(Collectors.toList()); }
4. 递归获取子节点的方法
/** * 递归获取子节点 * * @param m * @param menus * @return java.util.List<com.pfms.master.entity.SysMenu> * @author chao.zhang * @date 2020/10/20 17:57 **/ private List<SysMenu> getChildren(SysMenu m, List<SysMenu> menus) { // 子节点parentId = 父节点ID return menus.stream().filter(m1 -> m.getId().equals(m1.getParentId())) .peek(m1 -> m1.setChildren(getChildren(m1, menus))).collect(Collectors.toList()); }
最新回复(0)