“树”这个结构,在计算机中应该是无处不在的。例如文件目录树,数据库树索引,组织机构树等等。对于JavaWeb开发工程师来说,比较常见的有菜单树,权限树,组织机构树等。这些树形结构的每一个节点通常是存在数据库表中的,并且每一个节点都是一条独立的数据。如下,这里规定pid为null的时候,为根节点
那么如何将这样的列表数据封装为树形结构的数据呢?结构如下
[ { "id": "0", "pid": null, "name": "全国", "children": [ { "id": "1", "pid": "0", "name": "广东省", "children": [ { "id": "4", "pid": "1", "name": "佛山市", "children": [ ] }, { "id": "5", "pid": "1", "name": "汕头市", "children": [ ] }, { "id": "6", "pid": "1", "name": "东莞市", "children": [ ] } ] }, { "id": "2", "pid": "0", "name": "湖北省", "children": [ { "id": "7", "pid": "2", "name": "黄冈市", "children": [ ] }, { "id": "8", "pid": "2", "name": "宜昌市", "children": [ ] }, { "id": "9", "pid": "2", "name": "襄阳市", "children": [ ] } ] }, { "id": "3", "pid": "0", "name": "河南省", "children": [ { "id": "10", "pid": "3", "name": "洛阳市", "children": [ ] }, { "id": "11", "pid": "3", "name": "开封市", "children": [ ] }, { "id": "12", "pid": "3", "name": "新乡市", "children": [ ] } ] } ] } ]
代码如下
1,节点类
package net.sunmonkey.datatotree; import java.util.LinkedList; import java.util.List; /** * 树结构节点对象类 * @author Wenqin Cheng */ public class NodeVo { private String id; private String pid; private String name; private List<NodeVo> children; public NodeVo() { children = new LinkedList<>(); } public NodeVo(String id, String pid, String name) { this.id = id; this.pid = pid; this.name = name; this.children = new LinkedList<>(); } 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 getName() { return name; } public void setName(String name) { this.name = name; } public List<NodeVo> getChildren() { return children; } public void setChildren(List<NodeVo> children) { this.children = children; } @Override public String toString() { return "NodeVo{" + "id='" + id + '\'' + ", pid='" + pid + '\'' + ", name='" + name + '\'' + ", children=" + children + '}'; } }
2,转换工具类
package net.sunmonkey.datatotree; import java.util.LinkedList; import java.util.List; /** * id,pid的列表数据转化为树形结构数据 * @author Wenqin Cheng */ public class ConvertUtil { public static List<NodeVo> getTreeData(List<NodeVo> list) { List<NodeVo> tree = new LinkedList<>(); if(null != list && !list.isEmpty()){ for(NodeVo nodeVo: list){ addToTreeNodeList(list, nodeVo); } for (NodeVo nodeVo: list){ if(null == nodeVo.getPid()){ tree.add(nodeVo); } } } return tree; } private static void addToTreeNodeList(final List<NodeVo> nodeVoList, NodeVo treeNodeVo){ if(null != nodeVoList && !nodeVoList.isEmpty()){ for(NodeVo parentNodeVo: nodeVoList){ if(parentNodeVo.getId().equals(treeNodeVo.getPid())){ List<NodeVo> children = parentNodeVo.getChildren(); boolean flag = true; for(NodeVo node: children){ if(treeNodeVo.getId().equals(node.getId())){ flag = false; } } if(flag){ children.add(treeNodeVo); } break; }else{ addToTreeNodeList(parentNodeVo.getChildren(), treeNodeVo); } } } } }
3,测试主方法
package net.sunmonkey.datatotree; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.LinkedList; import java.util.List; /** * 主方法 * @author Wenqin Cheng */ public class MainClass { static ObjectMapper objectMapper = new ObjectMapper(); public static void main(String[] args) throws Exception { List<NodeVo> list = new LinkedList<>(); list.add(new NodeVo("0", null, "全国")); list.add(new NodeVo("1", "0", "广东省")); list.add(new NodeVo("2", "0", "湖北省")); list.add(new NodeVo("3", "0", "河南省")); list.add(new NodeVo("4", "1", "佛山市")); list.add(new NodeVo("5", "1", "汕头市")); list.add(new NodeVo("6", "1", "东莞市")); list.add(new NodeVo("7", "2", "黄冈市")); list.add(new NodeVo("8", "2", "宜昌市")); list.add(new NodeVo("9", "2", "襄阳市")); list.add(new NodeVo("10", "3", "洛阳市")); list.add(new NodeVo("11", "3", "开封市")); list.add(new NodeVo("12", "3", "新乡市")); System.out.println("转换前数据:"); System.out.println(objectMapper.writeValueAsString(list)); List<NodeVo> result = ConvertUtil.getTreeData(list); System.out.println("转换后数据:"); System.out.println(objectMapper.writeValueAsString(result)); } }