文章目录
- 前言
- 一、List常用业务场景的两种数据类型?
- 二、封装Tree
- 1.针对List类型为实体类封装树
- 2.针对List类型为Map封装树
- 3.查找当前节点下所有子节点
- 总结
前言
在Java日常开发中,经常遇到需要组装数据格式为多层级递归树的形式给前端使用,根据具体的业务场景和数据结构封装树的工具类也是各种各样,那么有没有一种通用、简洁、容易理解且高效的方式实现这样的业务场景呢?
一、List常用业务场景的两种数据类型?
一般根据业务场景常用的数据结构类型有List<Entity>和List<Map>这两种数据类型,那么接下来针对这两种类型分别封装树结构
二、封装Tree
1.针对List类型为实体类封装树
实体类代码如下(示例):
import lombok.Data;
import java.util.List;
@Data
public class Entity {
private String gid; -- 主键
private String name; -- 名称
private String parentId; -- 所属父级
private List<Entity> children; -- 子集合
}
封装Tree代码如下(示例):
import java.util.*;
import org.springframework.util.CollectionUtils;
public class TreeUtil {
/**
* 构建树
* @param parent: 父级目录 入口初始化传 null
* @param all : 要封装的所有数据集合,包含上下级关系
*/
public static List<Entity> buildTree(Entity parent, List<Entity> all) {
if(CollectionUtils.isEmpty(all)) {
return Collections.emptyList();
}
if(Objects.isNull(parent)) {
return all.stream().filter(e -> "0".equals(e.getParentId())).filter(a -> {
a.setChildren(buildTree(a,all));
return true;
}).collect(Collectors.toList());
}else {
return all.stream().filter(e -> parent.getGid().equals(e.getParentId())).filter(a -> {
a.setChildren(buildTree(a,all));
return true;
}).collect(Collectors.toList());
}
}
}
2.针对List类型为Map封装树
封装Tree代码如下(示例):
import java.util.*;
import org.springframework.util.CollectionUtils;
public class TreeUtil {
/**
* 构建树
* @param root : 父级目录 入口初始化传 null
* @param all : 要封装的所有数据集合,包含上下级关系
*/
public static List<Map> buildTree(Map root, List<Map> all) {
if(CollectionUtils.isEmpty(all)) {
return Collections.emptyList();
}
if(Objects.isNull(root)) {
return all.stream().filter(e -> "0".equals(e.get("parent_id")))
.map(a -> {
a.put("children", buildTree(a,all));
return a;
}
).collect(Collectors.toList());
}else {
return all.stream().filter(e -> root.get("gid").equals(e.get("parent_id")))
.map(a -> {
a.put("children", buildTree(a,all));
return a;
}
).collect(Collectors.toList());
}
}
}
3.查找当前节点下所有子节点
import java.util.*;
import org.springframework.util.CollectionUtils;
public class TreeUtil {
/**
* 查找当前节点下所有子节点
* @param nodeId : 当前节点
* @param all : 所有节点数据查找目标集合
* @param result : 查找的当前节点及节点所有子节点集合
*/
public static void findNodeChild(String nodeId, List<Map> all, List<String> result) {
// 1、查找当前节点下的所有子节点
List<Map> child = all.stream().filter(a -> nodeId.equals(a.get("parent_id"))).collect(Collectors.toList());
// 2、添加当前节点
result.add(nodeId);
// 3、递归查找
if(!CollectionUtils.isEmpty(child)) {
child.stream().forEach(g -> {
findNodeChild(g.get("gid").toString(),all,result);
});
}
}
}
总结
调用方式:以上封装默认顶级父节点的parent_id赋值为"0"
// 1、调用树
List<Entity> all = jdbc; // 从数据库获取的需要封装的业务数据包含上下级关系那种
List<Entity> result = TreeUtil.buildTree(null,all); // 返回前端的树结构数据
// 2、查找当前节点及其下所有子节点
List<String> result = Lists.newArrayList(); // 当前节点及其下所有子节点gid集合
String nodeId = gid; // 前端传参当前节点gid
TreeUtil.findNodeChild(nodeId,all,result);