一、树形结构简介
首先构建树形结构,我们得知道什么是树形结构,如下图所示。
如上图所示,可以看出有四级菜单,这就是树形结构。
如果想更深入的了解树形结构,建议去查询数据结构中关于树的章节。
二、树形菜单的分析与制作
至此,我们开始正式分析树形菜单的制作。
首先制作树形菜单我们需要用到两个类,一个菜单实体(Menu),一个生成树形的工具类(MenuTree)。
分析:菜单实体(Menu),承载菜单信息
生成树形的工具类(MenuTree),三个方法,获取根节点,获取子树,生成树。
获取根节点:获取所有上级菜单ID是0,放在根节点集合中
获取子树:传入根节点,通过递归调用不停查找下级菜单是否还有下级,没有就将制作的菜单列表加入该根节点的children中
生成树:先调用获取根节点得到根节点集合,再遍历根节点集合,对每一个根节点获取子菜单
关于两个类的作用具体参见下面源码,我都有给注释,应该是蛮好理解的。
菜单实体
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "菜单实体")
public class Menu {
@ApiModelProperty("菜单ID")
private String id;
@ApiModelProperty("菜单名称")
private String name;
@ApiModelProperty("上级菜单ID")
private String pId;
@ApiModelProperty("下级菜单集合")
private List<Menu> children;
}
生成菜单列表工具类
public class MenuTree {
// 流程:数据库查出的菜单记录装载在承载菜单的列表中---
// 构建树(获取根节点,遍历根节点,对每一个根节点构建子树)---得到最终树形菜单
// 承载菜单的列表
private List<Menu> menuList = new ArrayList<>();
// 带参构造器,将数据库中的菜单数据记录,装载在我们承载菜单的列表中
public MenuTree(List<Menu> menuList){
this.menuList = menuList;
}
// 获取根节点
public List<Menu> getRootNode(){
List<Menu> rootNode = new ArrayList<>();
for (Menu menu : menuList) {
if (menu.getPId().equals("0")){
rootNode.add(menu);
}
}
return rootNode;
}
// 构建子树
public Menu buildChildren(Menu rootNode){
List<Menu> childrenTree = new ArrayList<>();
for (Menu menu : menuList) {
if (menu.getPId().equals(rootNode.getId())){
childrenTree.add(buildChildren(menu));
}
}
rootNode.setChildren(childrenTree);
return rootNode;
}
// 构建树
public List<Menu> buildTree(){
List<Menu> menus = getRootNode();
for (Menu menu : menus) {
buildChildren(menu);
}
return menus;
}
}
至此,属性菜单制作完毕,我们准备一些测试数据测试一下,是否成功!
三、树形菜单制作的测试
public class Test {
public static void main(String[] args) {
// ----------------------测试的菜单数据--------------------------
ArrayList<Menu> menus = new ArrayList<>();
menus.add(new Menu("1","一级","0",null));
menus.add(new Menu("2","一级","0",null));
menus.add(new Menu("3","一级","0",null));
menus.add(new Menu("4","二级","1",null));
menus.add(new Menu("5","二级","1",null));
menus.add(new Menu("6","二级","2",null));
menus.add(new Menu("7","三级","4",null));
menus.add(new Menu("8","三级","5",null));
menus.add(new Menu("9","三级","6",null));
// ----------------------测试的菜单数据--------------------------
// 以上数据实际应由数据库提供,本次测试写死
// 创建生成树的工具类,调用构造树方法得到树形菜单
List<Menu> menuList = new MenuTree(menus).buildTree();
// fastjson的JSON 将java对象转为JSON字符串
String jsonString = JSON.toJSONString(menuList);
System.out.println(jsonString);
}
}
// 这是控制台打印的JSON数据
[{"children":[{"children":[{"children":[],"id":"7","name":"三级","pId":"4"}],"id":"4","name":"二级","pId":"1"},{"children":[{"children":[],"id":"8","name":"三级","pId":"5"}],"id":"5","name":"二级","pId":"1"}],"id":"1","name":"一级","pId":"0"},{"children":[{"children":[{"children":[],"id":"9","name":"三级","pId":"6"}],"id":"6","name":"二级","pId":"2"}],"id":"2","name":"一级","pId":"0"},{"children":[],"id":"3","name":"一级","pId":"0"}]
我们将数据复制一下,去格式化一下,我用的是这个网站在线JSON校验格式化工具(Be JSON)
以下是格式化之后的数据,生成成功!!!
[{
"children": [{
"children": [{
"children": [],
"id": "7",
"name": "三级",
"pId": "4"
}],
"id": "4",
"name": "二级",
"pId": "1"
}, {
"children": [{
"children": [],
"id": "8",
"name": "三级",
"pId": "5"
}],
"id": "5",
"name": "二级",
"pId": "1"
}],
"id": "1",
"name": "一级",
"pId": "0"
}, {
"children": [{
"children": [{
"children": [],
"id": "9",
"name": "三级",
"pId": "6"
}],
"id": "6",
"name": "二级",
"pId": "2"
}],
"id": "2",
"name": "一级",
"pId": "0"
}, {
"children": [],
"id": "3",
"name": "一级",
"pId": "0"
}]
至此,我们的树形菜单分析与制作完毕,有不足之处望指出。