一、背景
在日常开发过程中,树形结构是一种非常常见的数据结构。它由节点组成,每个节点可以有多个子节点。这种结构在许多应用场景中都非常有用,例如文件系统、数据库索引、组织架构等。在Java
中,我们可以使用类和方法来表示树形结构,并实现对其进行操作的方法。
二、代码示例
2.1 通用树形BaseTree类
下面的通用类只是一个示例,大家可以根据自己项目的需求进行调整,比如id
是Long
类型的等等。
java
/**
* <p>Description: 统一树结构</p>
*/
@Data
@ApiModel(description = "统一树结构")
public class BaseTree<T> {
@ApiModelProperty("主键")
private String id;
@ApiModelProperty("父节点id")
private String parentId;
@ApiModelProperty("层级")
private Integer tier;
@ApiModelProperty("子节点")
private List<T> children = CollUtil.newArrayList();
}
2.2 实际返回VO
这里面的内容也可以根据自己实际要返回的数据,进行修改调整,下面只是一个示例:
java
/**
* <p>类型返回VO</p>
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(description = "<p>类型返回VO对象</p>")
public class TypeVO extends BaseTree<TypeVO> {
@ApiModelProperty(value = "类别编码")
private String code;
@ApiModelProperty(value = "类别名称")
private String name;
}
2.3 树形处理TreeUtils
工具类
逻辑也都很清晰,主要传入一个集合列表,然后找到parentId
不为空,或者传入就有parentId
,将其设置为层级为1的主节点,然后通过主节点依次往下查找子节点,构建子树里面采用了递归的方式进行处理。
java
public class TreeUtils {
/**
* 构建树(必须是有序的列表)
*/
public static <T extends BaseTree> List<T> buildTree(List<T> treeNodes, String root) {
List<T> trees = CollUtil.newArrayList();
for (T treeNode : treeNodes) {
if (CharSequenceUtil.isBlank(treeNode.getParentId()) || (ObjectUtil.isNotNull(root) && root.equals(treeNode.getParentId()))) {
// 遍历的数据为一级
treeNode.setTier(1);
trees.add(treeNode);
setChildrenTier(treeNode, treeNodes, 2); // 设置子节点的tier,从第二层开始,初始tier为2
}
}
return trees;
}
/**
* 构建子树
*/
private static <T extends BaseTree> void setChildrenTier(T parentNode, List<T> treeNodes, int tier) {
for (T it : treeNodes) {
if (CharSequenceUtil.isNotBlank(it.getParentId()) && it.getParentId().equals(parentNode.getId())) {
if (ObjectUtil.isNull(it.getChildren())) {
it.setChildren(CollUtil.newArrayList());
}
it.setTier(tier); // 设置节点的tier
parentNode.getChildren().add(it);
setChildrenTier(it, treeNodes, tier + 1); // 递归调用设置子节点的tier,tier加1
}
}
}
}
2.4 测试结果
下面列举了一个非常建议的测试案例,首先从数据库里面查询出所有的type
的数据,然后调用我们上面写好的TreeUtils
进行处理,代码如下所示:
java
@Override
public List<TypeVO> listAllTypesTrees() {
List<TypeVO> typeList = typebaseMapper.selectTypes();
return TreeUtils.buildTree(typeList, null);
}
调用结果json
:
json
{
"message": "操作成功",
"code": "0",
"data": [
{
"id": "4a7af8949d606024ee37acf3a578b96e",
"parentId": null,
"tier": 1,
"children": [
{
"id": "29486803c75db91ea90722ea7db582ce",
"parentId": "4a7af8949d606024ee37acf3a578b96e",
"tier": 2,
"children": [],
"code": "11",
"name": "type1-1",
},
{
"id": "406727615a6c2859d1ca8f3a4f80069a",
"parentId": "4a7af8949d606024ee37acf3a578b96e",
"tier": 2,
"children": [],
"code": "12",
"name": "type1-2"
}
],
"code": "1",
"name": "type1"
},
{
"id": "9eed152b4e20ff10e76b33f5dd8cc4d2",
"parentId": null,
"tier": 1,
"children": [],
"code": "2",
"name": "type2"
},
{
"id": "d1fcdbf4da384bf454aa14276cee25b1",
"parentId": null,
"tier": 1,
"children": [],
"code": "3",
"name": "type3"
}
]
}
三、总结
Java
接口返回树形结构的方式主要有以下几种:1. 使用嵌套的List
;2. 使用递归方法;3. 使用JSON
格式的数据。这些方式的优势在于可以方便地表示和处理具有层级关系的数据,使得代码更加简洁、易读。同时,通过接口返回树形结构,可以实现数据的动态加载,提高系统的性能。此外,使用JSON
格式的数据还可以方便地进行跨平台的数据交换和解析。总之,Java
接口返回树形结构的方式在处理复杂数据结构时具有很大的优势,有助于提高代码的可维护性和扩展性。