递归实现树结构数据
一、递归概念:自己的理解,自己调用自己,何为自己调用自己,比如
下面的**chilMenus.add(buildChilTree(menuNode))**就是在自己调用自己,查询到下一级的下一级,有几级我就调用几次我自己,从而实现树状结构中的父节点下的所有子级。
注:后面有 JDK 8 的写法,如果有涉及到模糊匹配,建议前端匹配,后端处理麻烦且做不到完美,不建议后端处理。
//递归,建立子树形结构
public Menu buildChilTree(Menu pNode){
List<Menu> chilMenus =new ArrayList<Menu>();
for(Menu menuNode : menuList) {
if(menuNode.getParentId().equals(pNode.getId())) {
chilMenus.add(buildChilTree(menuNode));
}
}
pNode.setChildren(chilMenus);
return pNode;
}
那么,上代码:
①实体类
package recursion;
import java.util.List;
public class Menu {
private String id;
private String parentId;
private String text;
private String url;
private String yxbz;
private List<Menu> children;
public Menu(String id,String parentId,String text,String url,String yxbz) {
this.id=id;
this.parentId=parentId;
this.text=text;
this.url=url;
this.yxbz=yxbz;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getYxbz() {
return yxbz;
}
public void setYxbz(String yxbz) {
this.yxbz = yxbz;
}
public List<Menu> getChildren() {
return children;
}
public void setChildren(List<Menu> children) {
this.children = children;
}
@Override
public String toString() {
return "Menu{" +
"id='" + id + '\'' +
", parentId='" + parentId + '\'' +
", text='" + text + '\'' +
", url='" + url + '\'' +
", yxbz='" + yxbz + '\'' +
", children=" + children +
'}';
}
}
② getRootNode()获取根节点(父节点),buildChilTree(获取所有子节点),builTree整合子节点和父节点的数据,实现树结构
package recursion;
import java.util.ArrayList;
import java.util.List;
public class MenuTree{
private List<Menu> menuList = new ArrayList<Menu>();
public MenuTree(List<Menu> menuList) {
this.menuList=menuList;
}
//建立树形结构
public List<Menu> builTree(){
List<Menu> treeMenus =new ArrayList<Menu>();
for(Menu menuNode : getRootNode()) {
menuNode=buildChilTree(menuNode);
treeMenus.add(menuNode);
}
return treeMenus;
}
//递归,建立子树形结构
public Menu buildChilTree(Menu pNode){
List<Menu> chilMenus =new ArrayList<Menu>();
for(Menu menuNode : menuList) {
if(menuNode.getParentId().equals(pNode.getId())) {
chilMenus.add(buildChilTree(menuNode));
}
}
pNode.setChildren(chilMenus);
return pNode;
}
//获取根节点(获取所有的父节点)
public List<Menu> getRootNode() {
List<Menu> rootMenuLists =new ArrayList<Menu>();
for(Menu menuNode : menuList) {
if(menuNode.getParentId().equals("0")) {
rootMenuLists.add(menuNode);
}
}
return rootMenuLists;
}
}
③ 测试类
package recursion;
import com.alibaba.fastjson.JSON;
import java.util.ArrayList;
import java.util.List;
public class Recursion {
public static void main(String[] args) {
List<Menu> menuList= new ArrayList<Menu>();
/*插入一些数据*/
menuList.add(new Menu("GN001D000","0","系统管理","/admin","Y"));
menuList.add(new Menu("GN001D100","GN001D000","权限管理","/admin","Y"));
menuList.add(new Menu("GN001D110","GN001D100","密码修改","/admin","Y"));
menuList.add(new Menu("GN001D120","GN001D100","新加用户","/admin","Y"));
menuList.add(new Menu("GN001D200","GN001D000","系统监控","/admin","Y"));
menuList.add(new Menu("GN001D210","GN001D200","在线用户","/admin","Y"));
//让我们创建树
MenuTree menuTree =new MenuTree(menuList);
menuList=menuTree.builTree();
//转为json看看效果
String jsonOutput= JSON.toJSONString(menuList);
System.out.println(jsonOutput);
}
}
总结:要仔细观察,和琢磨,不能走马观花,看获取子节点时,仔细些,思考为什么要这么写,什么是递归,真正的理解递归的思想,就没有啥难度了。
后期追加,JDK 8 版本:
实体类: Tree , 注意这里的构造方法
@Data
public class Tree {
public Tree() {
}
public Tree(String id, String pid, String name) {
this.id = id;
this.pid = pid;
this.name = name;
}
String id;
String pid;
String name;
List<Tree> child;
}
public static void main(String[] args) {
List<Tree> treeList = new ArrayList<>();
//大哥的 PID 在这种写法里面不能为 null,负责 下面 filter 的时候会报错,因为它需要遍历对比
treeList.add(new Tree("0","","老大"));
treeList.add(new Tree("2","0","老二"));
treeList.add(new Tree("3","2","老三"));
treeList.add(new Tree("5","3","老四"));
treeList.add(new Tree("6","3","老四"));
treeList.add(new Tree("4","2","老三"));
treeList.add(new Tree("7","4","老四"));
String id = "0";
//包含本级,不需要可以删除
Tree tree = treeList.stream().filter(m -> m.getId().equals(id)).collect(Collectors.toList()).get(0);
List<Tree> test = test(treeList, id);
tree.setChild(test);
System.out.println("第一种方法:"+tree);
List<Tree> trees = test1(treeList, id);
System.out.println("第二种方法:"+trees);
}
public static List<Tree> test1(List<Tree> treeList,String id){
//获取父节点
List<Tree> resultList = new ArrayList<>(); //不需要本级可直接删除
List<Tree> collect = treeList.stream().filter(m -> {
//添加自己
if (m.getId().equals(id)) resultList.add(m); 不需要本级可直接删除
return m.getPid().equals(id);
}).map(
(m)->{
m.setChild(getChild1(m,treeList));
return m;
}
).collect(Collectors.toList());
//把自己的儿子添加到自己下面,不需要本级可直接删除,返回 collect
if (resultList.size()>0) resultList.get(0).setChild(collect);
return resultList;
}
private static List<Tree> getChild1(Tree tree, List<Tree> treeList) {
//获取字节点
List<Tree> collect = treeList.stream().filter(m -> m.getPid().equals(tree.getId())).map(
(m)->{
m.setChild(getChild(m,treeList));
return m;
}
).collect(Collectors.toList());
return collect;
}
public static List<Tree> test(List<Tree> treeList,String id){
//获取父节点
List<Tree> collect = treeList.stream().filter(m -> m.getPid().equals(id)).collect(Collectors.toList());
collect.stream().forEach(m->m.setChild(getChild(m,treeList)));
return collect;
}
private static List<Tree> getChild(Tree tree, List<Tree> treeList) {
//获取字节点
List<Tree> collect = treeList.stream().filter(m -> m.getPid().equals(tree.getId())).collect(Collectors.toList());
collect.stream().forEach(m->m.setChild(getChild(m,treeList)));
return collect;
}
原文链接:Java递归生成树状结构菜单