目录
准备工作
递归实现
未带有显示顺序的递归遍历
准备工作
create table dormitory_management.fuzi
(menu_id bigint auto_increment comment '菜单ID'primary key,menu_name varchar(50) not null comment '菜单名称',parent_id bigint default 0 null comment '父菜单ID',display_order int default 0 null comment '显示顺序'
);-- 添加中文测试数据
INSERT INTO dormitory_management.fuzi (menu_name, parent_id, display_order) VALUES
('顶级菜单1', 0, 1),
('顶级菜单2', 0, 2),
('子菜单1-1', 1, 1),
('子菜单1-2', 1, 2),
('子菜单2-1', 2, 1);
@Data
@ToString
public class Fuzi {private Long menuId;private String menuName;private Long parentId;private Long displayOrder;private List<Fuzi> children; // 子菜单列表
}
递归实现
//Service层
public interface FuziService extends IService<Fuzi> {List<Fuzi> getFuziMenuTreeWithoutChildren();List<Fuzi> buildMenuTree(List<Fuzi> menuList);
}
package com.lyh.mp.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyh.mp.entity.Fuzi;
import com.lyh.mp.mapper.FuziMapper;
import com.lyh.mp.service.FuziService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.*;/*** @author Mtz* @version 1.0* @2024/2/2015:49* @function* @comment*/
@Service
public class FuziServiceImpl extends ServiceImpl<FuziMapper, Fuzi> implements FuziService {@Autowiredprivate FuziMapper fuziMapper;public List<Fuzi> getFuziMenuTreeWithoutChildren() {QueryWrapper<Fuzi> fuzi = new QueryWrapper<>();fuzi.select("menu_id", "menu_name", "parent_id","display_order"); // 指定查询的字段List<Fuzi> menuList = fuziMapper.selectList(fuzi);return buildMenuTree(menuList); // 构建菜单树}// 构建父子级菜单树public List<Fuzi> buildMenuTree(List<Fuzi> menuList) {Map<Long, Fuzi> menuMap = new HashMap<>();// 将菜单放入Map中,以菜单ID作为键for (Fuzi menu : menuList) {menuMap.put(menu.getMenuId(), menu);}// 遍历菜单列表,将子菜单添加到对应的父菜单的children属性中List<Fuzi> treeMenu = new ArrayList<>();for (Fuzi menu : menuList) {Long parentId = menu.getParentId();if (parentId == null || parentId == 0) {// 顶级菜单treeMenu.add(menu);} else {// 子菜单Fuzi parentMenu = menuMap.get(parentId);if (parentMenu != null) {if (parentMenu.getChildren() == null) {parentMenu.setChildren(new ArrayList<>());}parentMenu.getChildren().add(menu);}}}// 对顶级菜单及其子菜单按照 display_order 排序sortTreeMenu(treeMenu);return treeMenu;}// 递归排序树形结构的菜单private void sortTreeMenu(List<Fuzi> treeMenu) {for (Fuzi menu : treeMenu) {if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {// 递归排序子菜单sortTreeMenu(menu.getChildren());}}// 对当前层级的菜单按照 display_order 排序Collections.sort(treeMenu, Comparator.comparingLong(Fuzi::getDisplayOrder));}/*- Fuzi(menuId=1, menuName=顶级菜单1, parentId=0, displayOrder=1, children=[- Fuzi(menuId=3, menuName=子菜单1-1, parentId=1, displayOrder=1, children=null),- Fuzi(menuId=4, menuName=子菜单1-2, parentId=1, displayOrder=2, children=null)])- Fuzi(menuId=2, menuName=顶级菜单2, parentId=0, displayOrder=2, children=[- Fuzi(menuId=5, menuName=子菜单2-1, parentId=2, displayOrder=1, children=null)])*/
}
未带有显示顺序的递归遍历
public List<Fuzi> getFuziMenuTreeWithoutChildren() {QueryWrapper<Fuzi> fuzi = new QueryWrapper<>();fuzi.select("menu_id", "menu_name", "parent_id"); // 指定查询的字段List<Fuzi> menuList = fuziMapper.selectList(fuzi);return buildMenuTree(menuList); // 构建菜单树}// 构建父子级菜单树public List<Fuzi> buildMenuTree(List<Fuzi> menuList) {Map<Long, Fuzi> menuMap = new HashMap<>();// 将菜单放入Map中,以菜单ID作为键for (Fuzi menu : menuList) {menuMap.put(menu.getMenuId(), menu);}System.out.println(menuMap);// 遍历菜单列表,将子菜单添加到对应的父菜单的children属性中List<Fuzi> treeMenu = new ArrayList<>();for (Fuzi menu : menuList) {Long parentId = menu.getParentId();if (parentId == null || parentId == 0) {// 顶级菜单treeMenu.add(menu);} else {// 子菜单Fuzi parentMenu = menuMap.get(parentId);if (parentMenu != null) {if (parentMenu.getChildren() == null) {parentMenu.setChildren(new ArrayList<>());}parentMenu.getChildren().add(menu);}}}return treeMenu;}