可以做网站首页的图片素材,工业和信息化部关于开展加强网站备案管理专项行动的通知,山西定制网站建设电源,wordpress加载慢 2017引言#xff1a; 在日常开发中#xff0c;我们经常会遇到需要将数据库中返回的数据转成树形结构的数据返回#xff0c;或者需要对转为树结构后的数据绑定层级关系再返回#xff0c;比如需要统计当前节点下有多少个节点等#xff0c;因此我们需要封装一个ListToTree的工具类…引言 在日常开发中我们经常会遇到需要将数据库中返回的数据转成树形结构的数据返回或者需要对转为树结构后的数据绑定层级关系再返回比如需要统计当前节点下有多少个节点等因此我们需要封装一个ListToTree的工具类和学会如何通过深度优先遍历数据。
数据准备 先简单准备一下具有父子关系的数据。
package data;public class OrgData {private String id;private String pId;private String orgName;public String getId() {return id;}public void setId(String id) {this.id id;}public String getpId() {return pId;}public void setpId(String pId) {this.pId pId;}public String getOrgName() {return orgName;}public void setOrgName(String orgName) {this.orgName orgName;}
}package data;import java.util.ArrayList;
import java.util.List;public class SingData {public static ListOrgData getData() {OrgData orgData1 new OrgData();orgData1.setId(1);orgData1.setpId(root);orgData1.setOrgName(根节点A);OrgData orgData2 new OrgData();orgData2.setId(2);orgData2.setpId(root);orgData2.setOrgName(根节点B);OrgData orgData3 new OrgData();orgData3.setId(3);orgData3.setpId(1);orgData3.setOrgName(A目录);OrgData orgData4 new OrgData();orgData4.setId(4);orgData4.setpId(2);orgData4.setOrgName(B目录);ListOrgData list new ArrayList();list.add(orgData1);list.add(orgData2);list.add(orgData3);list.add(orgData4);return list;}
}正常情况下我们都会选择封装一个将List转换为Tree的工具类并且通过链式顺序LinkedList存储来遍历Tree数据这里使用stream来实现如下
package data;import java.util.List;public class TreeBean {private String treeId;private String treePid;private String orgName;private Integer flag 0;private ListTreeBean children;private OrgData orgData;public String getTreeId() {return treeId;}public void setTreeId(String treeId) {this.treeId treeId;}public String getOrgName() {return orgName;}public void setOrgName(String orgName) {this.orgName orgName;}public String getTreePid() {return treePid;}public void setTreePid(String treePid) {this.treePid treePid;}public ListTreeBean getChildren() {return children;}public void setChildren(ListTreeBean children) {this.children children;}public OrgData getOrgData() {return orgData;}public void setOrgData(OrgData orgData) {this.orgData orgData;}public Integer getFlag() {return flag;}public void setFlag(Integer flag) {this.flag flag;}Overridepublic String toString() {return TreeBean{ treeId treeId \ , treePid treePid \ , orgName orgName \ , children children };}
}执行结果
620fc2d13f944d61888c2f0af8198ad2.png
对tree数据进行遍历通过链表的形式
import data.OrgData;
import data.SingData;
import data.TreeBean;
import utils.ListToTreeUtil;import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;public class Main {public static void main(String[] args) {// 模拟查询数据ListOrgData orgDataList SingData.getData();// 构建tree数据ListTreeBean treeBean ListToTreeUtil.toTree(orgDataList, root);// 使用LinkedList实现链式队列实现深度遍历LinkedListTreeBean stack new LinkedList();stack.addAll(treeBean);while (!stack.isEmpty()) {// 从栈顶开始访问TreeBean pop stack.peek();// Flag1表示已经遍历过一次且该节点存在子节点if (pop.getFlag() 1) {OrgData orgData pop.getOrgData();ListTreeBean children pop.getChildren();// 获取子节点的节点名称也可以进行其他的操作ListString collect children.stream().map(TreeBean::getOrgName).collect(Collectors.toList());StringBuilder builder new StringBuilder();for (String s : collect) {builder.append(s);builder.append();}pop.setOrgName(builder.toString());orgData.setOrgName(pop.getOrgName());// pop出栈当前节点已经统计完出栈获取下一个栈顶peekstack.pop();} else {// flag为0表示未遍历判断是否已经遍历到叶子节点(最底部)if (pop.getChildren()! null !pop.getChildren().isEmpty()) {// 非叶子节点pop.setFlag(1);ListTreeBean children pop.getChildren();for (TreeBean child : children) {// 将叶子节点入栈放到栈顶实现深度遍历nextstack.push(child);}} else {// 叶子节点直接出栈即可cnt为本身stack.pop();}}}// 遍历最终的数据for (OrgData orgData : orgDataList) {System.out.println(orgData.toString());}}
}但是现在有一个问题当我们响应的数据从OrgData换到其他类型的时候这时候就需要封装成一个泛型类使得我们的tree数据生成类变成一个通用的完整代码如下 完整代码JAVA将List转为Tree和深度优先遍历
package data;import java.util.List;public interface TreeT {String getTreeId();String getTreePid();void setChild(ListT list);
}package data;import java.util.List;/*** 实现TreeOrgData并定义响应类型为本身* 定义转为树的参数返回
*/
public class OrgData implements TreeOrgData{private String id;private String pId;private String orgName;// 转成树需要的参数private Integer flag 0;private ListOrgData child;public String getId() {return id;}public void setId(String id) {this.id id;}public String getpId() {return pId;}public void setpId(String pId) {this.pId pId;}public String getOrgName() {return orgName;}public void setOrgName(String orgName) {this.orgName orgName;}public Integer getFlag() {return flag;}public void setFlag(Integer flag) {this.flag flag;}public ListOrgData getChild() {return child;}Overridepublic String toString() {return OrgData{ id id \ , pId pId \ , orgName orgName \ };}Overridepublic String getTreeId() {return id;}Overridepublic String getTreePid() {return pId;}Overridepublic void setChild(ListOrgData list) {this.child list;}
}ListToTree方法
package utils;import data.OrgData;
import data.SingData;
import data.Tree;
import data.TreeBean;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;/*** 将List转为Tree* T extends Tree告诉编译器有Tree的get方法**/
public class ListToTreeUtil {public static T extends Tree ListT toTree(ListT list, String root) {// 当根节点为null时定义一个初始值防止nullString treeRoot treeRoot;String finalRoot root;if (list.isEmpty()) {return new ArrayList();}// 构建Map数据// 根据pid分组获取所有的子节点集合MapString, ListT childMap list.stream().collect(Collectors.groupingBy(item - {String treePid item.getTreePid();if (treePid null) {treePid treeRoot;}return treePid;}));return list.stream().peek(data - {ListT children childMap.get(data.getTreeId());if (children ! null !children.isEmpty()) {data.setChild(children);}}).filter(data - data.getTreePid().equals(finalRoot)).collect(Collectors.toList());}
}深度优先遍历
import data.OrgData;
import data.SingData;
import data.TreeBean;
import utils.ListToTreeUtil;import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;public class Main {public static void main(String[] args) {// 模拟查询数据ListOrgData orgDataList SingData.getData();// 构建tree数据ListOrgData treeBean ListToTreeUtil.toTree(orgDataList, root);// 使用LinkedList实现链式队列实现深度遍历LinkedListOrgData stack new LinkedList();stack.addAll(treeBean);while (!stack.isEmpty()) {// 从栈顶开始访问OrgData pop stack.peek();// Flag1表示已经遍历过一次且该节点存在子节点if (pop.getFlag() 1) {ListOrgData children pop.getChild();// 获取子节点的节点名称也可以进行其他的操作ListString collect children.stream().map(OrgData::getOrgName).collect(Collectors.toList());StringBuilder builder new StringBuilder();for (String s : collect) {builder.append(s);builder.append();}pop.setOrgName(builder.toString());// pop出栈当前节点已经统计完出栈获取下一个栈顶peekstack.pop();} else {// flag为0表示未遍历判断是否已经遍历到叶子节点(最底部)if (pop.getChild()! null !pop.getChild().isEmpty()) {// 非叶子节点pop.setFlag(1);ListOrgData children pop.getChild();for (OrgData child : children) {// 将叶子节点入栈放到栈顶实现深度遍历nextstack.push(child);}} else {// 叶子节点直接出栈即可cnt为本身stack.pop();}}}// 遍历最终的数据for (OrgData orgData : orgDataList) {System.out.println(orgData.toString());}}
}