-
在网上搜了下list转树,大部分都是递归和两个for循环,无意间发现了这条博客/zhizhao/p/,感觉时间复杂度要好很多,同样的数据量递归和嵌套for循环要用5~6秒,而这种方法只要十毫秒左右(原理是把list转成map,利用map的特点)。但生成的树是json格式,所以就改写成下面这种返回值是list集合的。(一定要看到最后!!!)
-
要转换的模型:TreeDto
import com.alibaba.fastjson.JSON;
import lombok.Data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ListToTreeTest {
private static List<TreeDto> listToTree(List<TreeDto> oldList) {
Map<String, Object> newMap = new HashMap<>();
List<TreeDto> result = new ArrayList<>();
for (TreeDto treeDto : oldList) {
newMap.put(treeDto.getId(), treeDto);
}
for (TreeDto treeDto : oldList) {
TreeDto parent = (TreeDto) newMap.get(treeDto.getPid());
if (parent != null) {
if (parent.getChildren() == null) {
List<TreeDto> ch = new ArrayList<>();
ch.add(treeDto);
parent.setChildren(ch);
} else {
List<TreeDto> ch = parent.getChildren();
ch.add(treeDto);
parent.setChildren(ch);
}
} else {
result.add(treeDto);
}
}
return result;
}
public static void main(String[] args) {
List<TreeDto> testTree = new ArrayList<TreeDto>() {{
add(new TreeDto("1", "0", "第1层", "01"));
add(new TreeDto("11", "1", "第2层", "0101"));
add(new TreeDto("12", "1", "第2层", "0102"));
add(new TreeDto("2", "0", "第1层", "02"));
add(new TreeDto("3", "4", "第4层", "03"));
add(new TreeDto("4", "11", "第3层", "010101"));
}};
System.out.println(JSON.toJSONString(listToTree(testTree)));
}
@Data
static class TreeDto {
public TreeDto(String id, String pid, String name, String treeNo) {
this.id = id;
this.pid = pid;
this.name = name;
this.treeNo = treeNo;
}
private String id;
private String pid;//fatherid
private String name;
private String treeNo;
private List<TreeDto> children;
}
}
- 但是改成这样这个方法就不能通用了,然后再改,抽象出id,父id和子集,重写就能用,参考:/magonong/article/details/80179400
1抽象类:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public abstract class List2tree<N> {
/**
* 主键ID
*
* @param node
* @return
*/
protected abstract Serializable getKey(N node);
/**
* 父节点
*
* @param node
* @return
*/
protected abstract Serializable getParentId(N node);
/**
* 子节点
*
* @param node
* @return
*/
protected abstract List<N> getChildrens(N node);
protected abstract void setChildrens(List<N> nodes, N node);
/**
* 生成树方法
*
* @param oldList
* @return
*/
public List<N> listToTree(List<N> oldList) {
Map<Serializable, N> newMap = oldList.stream().collect(Collectors.toMap(this::getKey, N -> N));
List<N> result = new ArrayList<>();
oldList.forEach(tree -> {
N parent = newMap.get(getParentId(tree));
if (parent == null) {
result.add(tree);
} else {
List<N> ch = getChildrens(parent);
if (ch == null) {
ch = new ArrayList<>();
}
ch.add(tree);
setChildrens(ch, parent);
}
});
return result;
}
}
2测试:
import com.alibaba.fastjson.JSON;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
public class MainTest {
public static void main(String[] args) {
//重写
List2tree<TreeDto> list2tree2 = new List2tree<TreeDto>() {
@Override
public String getKey(TreeDto node) {
return node.getId();
}
@Override
protected String getParentId(TreeDto node) {
return node.getPid();
}
@Override
protected List<TreeDto> getChildrens(TreeDto node) {
return node.getChildren();
}
@Override
protected void setChildrens(List<TreeDto> nodes, TreeDto node) {
node.setChildren(nodes);
}
};
//模拟数据
List<TreeDto> list = new ArrayList<TreeDto>() {{
add(new TreeDto("1", "0", "第1层"));
add(new TreeDto("11", "1", "第2层"));
add(new TreeDto("12", "1", "第2层"));
add(new TreeDto("2", "0", "第1层"));
add(new TreeDto("3", "4", "第4层"));
add(new TreeDto("4", "11", "第3层"));
}};
System.out.println(JSON.toJSONString(list2tree2.listToTree(list)));
}
@Data
static class TreeDto {
public TreeDto(String id, String pid, String name) {
this.id = id;
this.pid = pid;
this.name = name;
}
private String id;
private String pid;//父id
private String name;
private List<TreeDto> children;
}
}
- 摸鱼的时候,被我发现了这条博客/wenxingchen/article/details/115749782里面使用了反射,递归并且使用函数实现重写,就模仿他改成了下面的究极无敌最终函数进化版 !!!
import com.alibaba.fastjson.JSON;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
public class List2tree {
/**
* listToTree
* @param target 需转换的数据
* @param getId 主键
* @param getParentId 父id (父id必须和主键相同类型)
* @param getChildren 子集
* @param setChildren 子集
* @return tree
*/
public static <T, R> List<T> listToTree(List<T> target, Function<T, R> getId, Function<T, R> getParentId,
Function<T, List<T>> getChildren, BiConsumer<T, List<T>> setChildren) {
Map<R, T> oldMap = target.stream().collect(Collectors.toMap(getId, T -> T));
List<T> result = new ArrayList<>();
target.forEach(tree -> {
T parent = oldMap.get(getParentId.apply(tree));
if (parent == null) {
result.add(tree);
} else {
List<T> ch = getChildren.apply(parent);
if (ch == null) {
ch = new ArrayList<>();
}
ch.add(tree);
setChildren.accept(parent, ch);
}
});
return result;
}
public static void main(String[] args) {
//模拟数据
List<TreeDto> list = new ArrayList<TreeDto>() {{
add(new TreeDto("1", "0", "第1层"));
add(new TreeDto("11", "1", "第2层"));
add(new TreeDto("12", "1", "第2层"));
add(new TreeDto("2", "0", "第1层"));
add(new TreeDto("3", "4", "第4层"));
add(new TreeDto("4", "11", "第3层"));
}};
System.out.println(JSON.toJSONString(List2tree.listToTree(list, TreeDto::getId, TreeDto::getPid,
TreeDto::getChildren, TreeDto::setChildren)));
}
@Data
static class TreeDto {
public TreeDto(String id, String pid, String name) {
this.id = id;
this.pid = pid;
this.name = name;
}
private String id;
private String pid;//父id
private String name;
private List<TreeDto> children;
}
}
- 有关 JDK8 | BiConsumer<T,U>实践应用 /shichen2010/article/details/108284064