前言
在日常的开发工作中,我们经常会遇到需要返回树结构的情况,在此记录下一般的处理方式。
树结构特点分析
树结构存在上下级关系,一般子节点会保存父节点的ID(parentId),很多人会采用递归的方式去处理,但通过map,两次循环遍历的办法,可以不用递归即可实现返回树结构。
代码示例
树节点实体:
/**
* 树节点
*
* @author xy
* @date 2022/12/4
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "树节点", description = "树节点")
public class TreeNode implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "父ID")
private Long parentId;
@ApiModelProperty(value = "编码")
private String code;
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value = "排序")
private Integer sort;
@ApiModelProperty(value = "子节点")
private List<TreeNode> children = new ArrayList<>();
public void addChild(TreeNode node){
children.add(node);
}
}
获取树结构方法:
public List<TreeNode> getTree() {
List<TreeNode> treeList = new ArrayList<>();
List<TreeNode> topNodeList = new ArrayList<>();
//获取树节点List
QueryWrapper<SysOrg> queryWrapper = Wrappers.<SysOrg>query().eq("deleted", 0);
List<SysOrg> orgList = sysOrgMapper.selectList(queryWrapper);
if (CollUtil.isNotEmpty(orgList)) {
Map<Long, TreeNode> map = new HashMap<>();
//第一次循环:构建树节点List,获取根节点List,构建Map
for (SysOrg org : orgList) {
TreeNode node = org2TreeNode(org);
if (node.getParentId() == null || node.getParentId() == 0L) {
topNodeList.add(node);
}
treeList.add(node);
map.put(node.getId(), node);
}
if (CollUtil.isNotEmpty(treeList) && CollUtil.isNotEmpty(topNodeList) && CollUtil.isNotEmpty(map)) {
//第二次循环:父节点添加子节点
for (TreeNode node : treeList) {
if(node.getParentId() != null && node.getParentId() != 0L){
TreeNode parent = map.get(node.getParentId());
if(ObjectUtil.isNotEmpty(parent)){
parent.addChild(node);
}else{
log.warn("机构树存在脏数据,该数据【{}】获取不到父节点",node);
}
}
}
}
}
return topNodeList;
}
实现效果:
注意:
此例中,判断根节点的条件是该节点的父ID为空或0,反之则为子节点,可根据实际业务情况做不同处理。