List数据转换成树
这里有两种思路,第一是使用递归,第二使用迭代。推荐使用迭代,不容易报错。
实体类
import lombok.Data;
import lombok.Getter;
import org.springframework.beans.BeanUtils;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Data
public class ExpertsBidAreaDemoDto implements Serializable {
private static final long serialVersionUID = 3835993471387471393L;
/**
* 记录ID
*/
private Long id;
/**
* 创建日期
*/
private Date createdAt;
/**
* 更新日期
*/
private Date updatedAt;
/**
* 父节点ID
*/
private Long parentId;
/**
* 名称
*/
private String name;
/****以下为扩展字段*****/
/**
* 子节点
*/
private List<ExpertsBidAreaDemoDto> childs;
/**
* 该节点下专家节点数
* 等于experts的size,主要是用来防止每次重复取值
*/
private Integer expertCounts;
/**
* 该节点下专家
*
*/
private Set<Long> experts;
}
递归解法
/**
* 自己先写一个list转tree的方法
*/
private List<ExpertsBidAreaDemoDto> transferFromListToTree(List<ExpertsBidAreaDemoDto> list) {
// 先找出根节点。
List<ExpertsBidAreaDemoDto> roots = new ArrayList<>();
for (ExpertsBidAreaDemoDto node : list) {
if (node.getParentId() == null) {
roots.add(node);
}
}
for (ExpertsBidAreaDemoDto root : roots) {
transfer(list, root);
}
return roots;
}
/**
* 通过递归将list转换为树
*
* @param list 所有节点的list集合
* @param root 树的根节点
*/
private void transfer(List<ExpertsBidAreaDemoDto> list, ExpertsBidAreaDemoDto root) {
// 叶子节点直接结束
if (root.getExpertCounts() != null) {
return ;
}
if (root.getChilds() == null) {
root.setChilds(new ArrayList<>());
}
// 先将第一层的加入
for (ExpertsBidAreaDemoDto node : list) {
// 如果是其子节点,则加入
if (node.getParentId() == root.getId()) {
root.getChilds().add(node);
}
}
// 递归将后续全部加入
for (ExpertsBidAreaDemoDto child : root.getChilds()) {
transfer(list, child);
}
}
迭代解法
/**
* list转换树的迭代版本
* @param list
* @return
*/
private List<ExpertsBidAreaDemoDto> transferFromListToTree(List<ExpertsBidAreaDemoDto> list) {
List<ExpertsBidAreaDemoDto> result = new ArrayList<>();
// 类似于出遍历子节点
for (ExpertsBidAreaDemoDto node1 : list) {
// 如果一直是false,没有改变,代表这个节点没有父节点,即为root节点
boolean flag = false;
// 第二次遍历,遍历出父节点
for (ExpertsBidAreaDemoDto node2 : list) {
// 最重要的判断还是node1.getParentId() == node2.getId() 前面的判断只是看最基本的条件是否满足
if (node1.getParentId() != null && !node1.getId().equals(node2.getId()) && node1.getParentId() == node2.getId()) {
// 标记node1有父节点,即不为根节点
flag = true;
if (node2.getChilds() == null) {
node2.setChilds(new ArrayList<>());
node2.getChilds().add(node1);
} else {
node2.getChilds().add(node1);
}
// 结束接下来的无意义的循环了,node1已经找到其父节点
break;
}
}
// 根节点
if (!flag) {
result.add(node1);
}
}
return result;
}