目录
准备工作
迭代实现
递归实现
未带有显示顺序的递归遍历
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 children; // 子菜单列表
}
分析图:
//Service层
public interface FuziService extends IService {
List getFuziMenuTreeWithoutChildren();
List buildMenuTree(List 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 implements FuziService {
@Autowired
private FuziMapper fuziMapper;
public List getFuziMenuTreeWithoutChildren() {
QueryWrapper fuzi = new QueryWrapper<>();
fuzi.select("menu_id", "menu_name", "parent_id","display_order"); // 指定查询的字段
List menuList = fuziMapper.selectList(fuzi);
return buildMenuTree(menuList); // 构建菜单树
}
// 构建父子级菜单树
public List buildMenuTree(List menuList) {
Map menuMap = new HashMap<>();
// 将菜单放入Map中,以菜单ID作为键
for (Fuzi menu : menuList) {
menuMap.put(menu.getMenuId(), menu);
}
// 遍历菜单列表,将子菜单添加到对应的父菜单的children属性中
List 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 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 buildMenuTree(List menuList) {
Map menuMap = new HashMap<>();
for (Fuzi menu : menuList) {
menuMap.put(menu.getMenuId(), menu);
}
List treeMenu = new ArrayList<>();
for (Fuzi menu : menuList) {
if (menu.getParentId() == null || menu.getParentId() == 0) {
buildChildMenu(menu, menuMap);
treeMenu.add(menu);
}
}
return treeMenu;
}
private void buildChildMenu(Fuzi parentMenu, Map menuMap) {
Long parentId = parentMenu.getMenuId();
List children = new ArrayList<>();
menuMap.values().stream()
.filter(menu -> parentId.equals(menu.getParentId()))
.forEach(menu -> {
buildChildMenu(menu, menuMap);
children.add(menu);
});
children.sort(Comparator.comparingLong(Fuzi::getDisplayOrder));
parentMenu.setChildren(children);
}
public List getFuziMenuTreeWithoutChildren() {
QueryWrapper fuzi = new QueryWrapper<>();
fuzi.select("menu_id", "menu_name", "parent_id"); // 指定查询的字段
List menuList = fuziMapper.selectList(fuzi);
return buildMenuTree(menuList); // 构建菜单树
}
// 构建父子级菜单树
public List buildMenuTree(List menuList) {
Map menuMap = new HashMap<>();
// 将菜单放入Map中,以菜单ID作为键
for (Fuzi menu : menuList) {
menuMap.put(menu.getMenuId(), menu);
}
System.out.println(menuMap);
// 遍历菜单列表,将子菜单添加到对应的父菜单的children属性中
List 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;
}