java构建树
先看看模拟的数据库的值(数据库名:company(公司))
可以根据parentId为0的数据为父节点,但是有些数据库根据不同的情况,设置了不同属性
| level(等级1为顶点) | id | parentId(父公司Id) | name(公司名) |
|---|---|---|---|
| 1 | 1 | 0 | 顶级节点A |
| 1 | 2 | 0 | 顶级节点B |
| 2 | 3 | 1 | 父节点是A |
| 2 | 4 | 2 | 父节点是B |
| 2 | 5 | 2 | 父节点是B |
| 3 | 6 | 3 | 父节点的ID是3 |
构建一棵树的步骤
1、首先获取所有的根节点(顶级节点),跟数据库的配置有关
2、根据每一个根节点,与所有节点集合(数据)进行判断,当前节点是否为其下的子节点。
3、若是,则递归调用构建树形;若不是,则表明该节点不属于其下子节点。
4、应继续循环判断节点父子关系,直到所有节点与根节点判断完毕。
/**
* 构造树(需要根据不同的情况变动)
* @return
*/
private List<TreeNode> constructionTree(List<Company> list) {
// 全部数据(由查找的数据遍历得到)
List<TreeNode> allList = new ArrayList<>();
// 根节点的数据
List<TreeNode> rootNodeList = new ArrayList<>();
// 最终的树结构
List<TreeNode> treeList = new ArrayList<>();
// 获取根节点
list.forEach(x -> {
// 这里就是说根节点是级别为1的值
if ("1".equals(x.getLevel())) {
TreeNode treeNode = new TreeNode()
.setKey(x.getId())
.setId(x.getId())
.setTitle(x.getName())
.setParentId(x.getParentId());
rootNodeList.add(treeNode);
}
});
// 构造树结构,这里可以执行过滤操作,把list(List<Data>)过滤成我们需要的参数(allList)
list.forEach(x->{
TreeNode treeNode = new TreeNode()
.setKey(x.getId())
.setId(x.getId())
.setTitle(x.getName())
.setParentId(x.getParentId());
allList.add(treeNode);
});
// 装配树干
for (TreeNode treeRootNode : rootNodeList) {
// 将顶级节点进行构建子树
treeRootNode = buildChildTree(treeRootNode,allList);
// 完成一个顶级节点所构建的树形,增加进来
treeList.add(treeRootNode);
}
return treeList;
}
/**
* 递归-----构建子树形结构
* @param pNode 根节点(顶级节点)
* @param treeList 全部数据
* @return 整棵树
*/
public TreeNode buildChildTree(TreeNode pNode, List<TreeNode> treeList){
List<TreeNode> childTree = new ArrayList<>();
// nodeList:所有节点集合(所有数据)
for (TreeNode treeNode : treeList) {
// 判断当前节点的父节点ID是否等于根节点的ID,即当前节点为其下的子节点
if (treeNode.getParentId().equals(pNode.getId())) {
// 再递归进行判断当前节点的情况,调用自身方法
childTree.add(buildChildTree(treeNode,treeList));
}
}
// for循环结束,即节点下没有任何节点,树形构建结束,设置树结果
pNode.setChildren(childTree);
return pNode;
}
TreeNode(树节点类)(用于封装转给前端),里面的值可以改动
/**
* TreeNode 树节点
*
* @author ZPA
* @date 2023年10月23日
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class TreeNode {
/** ID(前端需要对应公司的id) */
private String key;
/** 节点id */
private String id;
/** 父节点id:顶级节点为 0 */
private String parentId;
/** 节点名称(前端需要对应公司的name) */
private String title;
/** 子节点 */
private List<TreeNode> children;
}
Company(公司类)
/**
* 模拟公司
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Company {
/**
* 公司等级
*/
private String level;
/**
* 公司ID
*/
private String id;
/**
* 父公司ID
*/
private String parentId;
/**
* 公司名字
*/
private String name;
}
测试
public class TreeTest {
@Test
public void treeTest(){
// 模拟测试数据(模拟数据库的值)
List<Company> companyList = new ArrayList<>();
companyList.add(new Company("1","1","0","顶级节点A"));
companyList.add(new Company("1","2","0","顶级节点B"));
companyList.add(new Company("2","3","1","父节点是A"));
companyList.add(new Company("2","4","2","父节点是B"));
companyList.add(new Company("2","5","2","父节点是B"));
companyList.add(new Company("3","6","3","父节点的ID是3"));
TreeTest test = new TreeTest();
// 原查询结果转换树形结构
List<TreeNode> treeNodes = test.constructionTree(companyList);
System.out.println(treeNodes);
}
/**
* 构造树(需要根据不同的情况变动)
* @return
*/
private List<TreeNode> constructionTree(List<Company> list) {
// 全部数据(由查找的数据遍历得到)
List<TreeNode> allList = new ArrayList<>();
// 根节点的数据
List<TreeNode> rootNodeList = new ArrayList<>();
// 最终的树结构
List<TreeNode> treeList = new ArrayList<>();
// 获取根节点
list.forEach(x -> {
// 这里就是说根节点是级别为1的值
if ("1".equals(x.getLevel())) {
TreeNode treeNode = new TreeNode()
.setKey(x.getId())
.setId(x.getId())
.setTitle(x.getName())
.setParentId(x.getParentId());
rootNodeList.add(treeNode);
}
});
// 构造树结构,这里可以执行过滤操作,把list(List<Data>)过滤成我们需要的参数(allList)
list.forEach(x->{
TreeNode treeNode = new TreeNode()
.setKey(x.getId())
.setId(x.getId())
.setTitle(x.getName())
.setParentId(x.getParentId());
allList.add(treeNode);
});
// 装配树干
for (TreeNode treeRootNode : rootNodeList) {
// 将顶级节点进行构建子树
treeRootNode = buildChildTree(treeRootNode,allList);
// 完成一个顶级节点所构建的树形,增加进来
treeList.add(treeRootNode);
}
return treeList;
}
/**
* 递归-----构建子树形结构
* @param pNode 根节点(顶级节点)
* @param treeList 全部数据
* @return 整棵树
*/
public TreeNode buildChildTree(TreeNode pNode, List<TreeNode> treeList){
List<TreeNode> childTree = new ArrayList<>();
// nodeList:所有节点集合(所有数据)
for (TreeNode treeNode : treeList) {
// 判断当前节点的父节点ID是否等于根节点的ID,即当前节点为其下的子节点
if (treeNode.getParentId().equals(pNode.getId())) {
// 再递归进行判断当前节点的情况,调用自身方法
childTree.add(buildChildTree(treeNode,treeList));
}
}
// for循环结束,即节点下没有任何节点,树形构建结束,设置树结果
pNode.setChildren(childTree);
return pNode;
}
}
结果打印
[
{
"children": [
{
"children": [
{
"children": [],
"id": "6",
"key": "6",
"parentId": "3",
"title": "父节点的ID是3"
}
],
"id": "3",
"key": "3",
"parentId": "1",
"title": "父节点是A"
}
],
"id": "1",
"key": "1",
"parentId": "0",
"title": "顶级节点A"
},
{
"children": [
{
"children": [],
"id": "4",
"key": "4",
"parentId": "2",
"title": "父节点是B"
},
{
"children": [],
"id": "5",
"key": "5",
"parentId": "2",
"title": "父节点是B"
}
],
"id": "2",
"key": "2",
"parentId": "0",
"title": "顶级节点B"
}
]