1. 前 言
在实际的开发中,一些菜单页面需要返回的不是一张列表,而一个树形结构的数据;
近期项目中也有需要获取全国行政区划省-市-区县-乡镇的树状结构数据,现将自己加班学习的获取树的方法总结如下,可能有不足之处,心血来潮之作,也希望大家批评指正!
首先,先做一个简单的例子进行说明
2. 简 单 实 例
2.1 定义VO类
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(description = "用户信息-userVO")
public class UserVo {
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("父ID")
private Long parentId;
@ApiModelProperty("名称")
private String name;
@ApiModelProperty("子节点")
private List<UserVo> children;
@ApiModelProperty(value = "是否有孩子结点的标志")
@JsonIgnore
private Boolean flag = false;
// 添加结点到孩子结点集合
public void addChildren(UserVo userVo) {
this.children.add(userVo);
}
// 设置有孩子结点
public void hasChildren() {
if (this.flag) {
return;
}
this.flag = true;
this.children = new ArrayList<>();
}
}
2.2 Controller
public List<UserVO> userList(){
List<UserVO> resultVO = userService.getUserList();
return resultVO;
}
2.3 Service
public List<UserVO> getUserList(){
//一次性查询所有数据
List<userVO> users = userMapper.userList();
//存储UserVO->返回树形结构
List<UserVO> result = new ArrayList<>();
// 构造树形结构
for (int i = 0; i < users.size(); i++) {
userVO parent = users.get(i);
// 如果是根节点,则添加至树形结果列表
if (StringUtils.isBlank(parent.getParentId()) || StringUtils.equals(parent.getId(), parent.getParentId())) {
result.add(parent);
}
for (int j = 0; j < users.size(); j++) {
userVO children = users.get(j);
// 判断children是否是parent的孩子节点
if (StringUtils.equals(parent.getId(), children.getParentId())) {
parent.hasChildren();
parent.addChildren(children);
}
}
}
return result;
}
2.4 Mapper
略
3. 获取全国行政区划省-市-区县-乡镇的树状结构数据
3.1 定义VO类
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(description = "CategoryTreeVO")
public class CategoryTreeVO {
@ApiModelProperty(value = "主键id")
private long id;
@ApiModelProperty(value = "父id")
private long parentId;
@ApiModelProperty(value = "子节点")
private List<CategoryTreeVO> children = new ArrayList<>();
/* 此处两个方法可以结合到一处 -> children = new ArrayList<>();
// 添加结点到孩子结点集合
public void addChildren(UserVo userVo) {
this.children.add(userVo);
}
// 设置有孩子结点
public void hasChildren() {
if (this.flag) {
return;
}
this.flag = true;
this.children = new ArrayList<>();
}*/
}
3.2 Controller
public List<CategoryTreeVO> CategoryTreeList(){
List<CategoryTreeVO> resultVO = areaTreeService.getCategoryTreeList();
return resultVO;
}
3.3 Service
public List<CategoryTreeVO> getCategoryTreeList() {
//一次性查询所有数据
List<CategoryTreeVO> list= categoryTreeMapper.getCategoryTreeList();
//存储树形结构
List<CategoryTreeVO> result = new ArrayList<>();
TreeUtil treeUtilNew = new TreeUtil();
result = treeUtilNew.build(list); //进行封装
return result; //返回树形结构
}
3.4 Mapper
略
3.5 TreeUtil的编写
public class TreeUtil {
/**
* 根据pid,构建树节点
*/
public static <T extends CategoryTreeVO> List<T> build(List<T> treeNodes, Integer pid) {
List<T> treeList = new ArrayList<>();
for(T treeNode : treeNodes) {
if (pid.equals(treeNode.getParentId())) {
treeList.add(findChildren(treeNodes, treeNode));
}
}
return treeList;
}
/**
* 查找子节点
*/
private static <T extends CategoryTreeVO> T findChildren(List<T> treeNodes, T rootNode) {
for(T treeNode : treeNodes) {
if(rootNode.getId().equals(treeNode.getParentId())) {
rootNode.getChildren().add(findChildren(treeNodes, treeNode));
}
}
return rootNode;
}
/**
* 构建树节点
*/
public static <T extends CategoryTreeVO> List<T> build(List<T> treeNodes) {
List<T> result = new ArrayList<>();
//list转map
Map<BigInteger, T> nodeMap = new LinkedHashMap<>(treeNodes.size());
for(T treeNode : treeNodes){
nodeMap.put(treeNode.getId(), treeNode);
}
for(T node : nodeMap.values()) {
T parent = nodeMap.get(node.getParentId());
if(parent != null && !(node.getId().equals(parent.getId()))){
parent.getChildren().add(node);
continue;
}
result.add(node);
}
return result;
}
}
总结
以上是我从最近的项目中学到的返回树形结构的方法