基础类:
public class TreeNodeDto {
private String id;
private String parentId;
/**
* 节点名称
*/
private String nodeName;
private String nodeType;
private String iconUrl;
/**
* 叶子节点业务id
*/
private String businessId;
/**
* 节点排序号
*/
private Integer treeSort = 0;
private List<TreeNodeDto> childList;
}
list转tree递归转换
/**
* 递归遍历生成树结构
* @param list
* @param parentId
* @return
*/
public List<TreeNodeDto> findChildrenList(List<TreeNodeDto> list, String parentId) {
List<TreeNodeDto> trees = new ArrayList<>();
//获取到所有parentCode的子节点
for (TreeNodeDto item : list) {
if (parentId.equals(item.getParentId())) {
trees.add(item);
//递归遍历该子节点的子节点列表
item.setChildList(this.findChildrenList(list, item.getParentId()));
}
}
return trees;
}
假设有列表有n个元素要组成一颗树,时间复杂度为O(n2), 每次递归都会创建一个treeList对象,空间复杂度为O(n)
这个递归可能当数据量太大时会造成方法栈内存溢出,不是很想使用这个方法。
双重for循环转tree
public class TreeNodeUtil {
/**
* 双重for循环 生成树结构
* @param list
* @param parentId
* @return
*/
public static List<TreeNodeDto> convertTree(List<TreeNodeDto> list, String parentId) {
List<TreeNodeDto> trees = new ArrayList<>();
for (TreeNodeDto item : list) {
//只将根节点添加到trees树的根中
if (parentId.equals(item.getParentId())) {
trees.add(item);
}
// 查询当前节点的所有子节点,设置到当前节点下
for (TreeNodeDto childItem : list) {
// 父节点id和外层循环的节点id相等,表示归属于外层循环节点的子节点,加入到列表
if (item.getId().equals(childItem.getParentId())) {
if (item.getChildList() == null) {
item.setChildList(new ArrayList<TreeNodeDto>());
}
item.getChildList().add(childItem);
}
}
}
return trees;
}
}
上面双重for循环,
最外层循环的作用是:
1、过滤获取指定父节点下根节点作为一颗树列表的根节点。(树列表只存储根节点,其他分支都是根节点上追加)
2、还有一个作用是,遍历所有节点的子节点列表
第二层for循环就是用来查找节点的字节点。
还有一种,使用Map<id, object>存放id 和对象本身。查询父节点id时,直接map.get( parentID)获取父节点对象,追加到父节点的childList中。
/**
* Map存放key值进行转换
* @param list
* @param parentId
* @return
*/
public List<TreeNodeDto> convertTreeUseMap(List<TreeNodeDto> list, String parentId) {
Map<String, TreeNodeDto> mapData = new HashMap<>();
List<TreeNodeDto> rootData = new ArrayList<>();
for (TreeNodeDto item : list) {
// 全部放入map中
if (item.getParentId().equals(parentId)) {
rootData.add(item);
}
mapData.put(item.getId(), item);
}
for (TreeNodeDto item : list) {
// 一次性把所有列表组合成树
String tmpParentId = item.getParentId();
// 排除根节点
if (tmpParentId.equals(parentId)) {
continue;
}
TreeNodeDto parent = mapData.get(tmpParentId);
if (parent.getChildList() == null) {
parent.setChildList(new ArrayList<>());
}
parent.getChildList().add(item);
}
return rootData;
}
可能还会有需求时,树结构要按照排序号进行同级节点的排序,可以递归获取字列表,或者for循环获取字列表后进行list排序
参考资料
java list 转树 tree 的三种写法:https://blog.csdn.net/jcroad/article/details/79735790#commentBox