还在使用递归生成树形结构?太慢!使用HashMap用空间换时间,一次遍历即可构建树形结构。后面将使用泛型和函数式编程优化,完成一个通用的树形结构生成工具。
public class TreeTest {
public static void main(String[] args) {
// 构建测试数据
List<Dept> depts = generateDepts();
long start = System.currentTimeMillis();
List<Dept> topDepts = new ArrayList<>();
Map<String, List<Dept>> map = new HashMap<>();
for (Dept dept : depts) {
// 构建自己的子部门列表
String id = dept.getId();
if (!map.containsKey(id)) {
map.put(id, new ArrayList<>());
}
dept.setChildren(map.get(id));
// 把自己加到父部门的子部门列表
String pid = dept.getPid();
if (!map.containsKey(pid)) {
map.put(pid, new ArrayList<>());
}
map.get(pid).add(dept);
// 顶级部门放到列表中
if (dept.getPid() == null) {
topDepts.add(dept);
}
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
private static List<Dept> generateDepts() {
// 生成层级有5,每一层20个部门的部门列表,顶级部门的pid约定为null
List<Dept> depts = generateDepts(20, 5, null);
// 打乱列表的数据
Collections.shuffle(depts);
return depts;
}
private static List<Dept> generateDepts(int num, int d, String pid) {
if (d == 0) {
return Collections.emptyList();
}
List<Dept> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
String id = UUID.randomUUID().toString();
list.add(new Dept(id, pid));
// 递归生成以当前id为pid的子部门列表
list.addAll(generateDepts(num, d - 1, id));
}
return list;
}
public static class Dept {
private String id;
private String pid;
private List<Dept> children;
public Dept(String id, String pid) {
this.id = id;
this.pid = pid;
}
public String getId() {
return id;
}
public Dept setId(String id) {
this.id = id;
return this;
}
public String getPid() {
return pid;
}
public Dept setPid(String pid) {
this.pid = pid;
return this;
}
public List<Dept> getChildren() {
return children;
}
public Dept setChildren(List<Dept> children) {
this.children = children;
return this;
}
@Override
public String toString() {
return "Dept{" +
"id='" + id + '\'' +
", pid='" + pid + '\'' +
", children=" + children +
'}';
}
}
}
使用泛型和函数式编程优化,如下
public static void main(String[] args) {
// 构建测试数据
List<Dept> depts = generateDepts();
long start = System.currentTimeMillis();
Function<Dept, String> getIdFunc = Dept::getId;
Function<Dept, String> getPidFunc = Dept::getPid;
BiConsumer<Dept, List<Dept>> setChildrenConsumer = Dept::setChildren;
Predicate<Dept> isTopPred = dept -> Objects.isNull(dept.getPid());
List<Dept> topList = generateTree(depts, getIdFunc, getPidFunc, setChildrenConsumer, isTopPred);
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public static <T> List<T> generateTree(List<T> list,
Function<T, String> getIdFunc,
Function<T, String> getPidFunc,
BiConsumer<T, List<T>> setChildrenConsumer,
Predicate<T> isTopPred) {
List<T> topList = new ArrayList<>();
Map<String, List<T>> map = new HashMap<>();
for (T obj : list) {
// 构建自己的子列表
String id = getIdFunc.apply(obj);
if (!map.containsKey(id)) {
map.put(id, new ArrayList<>());
}
setChildrenConsumer.accept(obj, map.get(id));
// 把自己加到父对象的子列表
String pid = getPidFunc.apply(obj);
if (!map.containsKey(pid)) {
map.put(pid, new ArrayList<>());
}
map.get(pid).add(obj);
// 是否顶级
if (isTopPred.test(obj)) {
topList.add(obj);
}
}
return topList;
}