根据反射获取相关字段进行比对以生成树,代码比较简单,就不做过多说明了。
package xyz.iotcode.xs.starter.common.util;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import java.lang.reflect.Field;
import java.util.*;
/**
* @author xieshuang
* @date 2020-08-13 15:14
*/
public class TreeUtils<T> {
public List<T> longTree(List<T> list) throws IllegalAccessException {
return tree(list, "id", "pid", "child", 0L);
}
public List<T> intTree(List<T> list) throws IllegalAccessException {
return tree(list, "id", "pid", "child", 0);
}
public List<T> stringTree(List<T> list) throws IllegalAccessException {
return tree(list, "id", "pid", "child", "0");
}
public List<T> tree(List<T> list, String idName, String pidName, String childName, Object topValue) throws IllegalAccessException {
if (CollUtil.isEmpty(list)){
return Collections.emptyList();
}
Class<?> aClass = list.get(0).getClass();
Map<String, Field> vFieldMap = getAllFieldMap(aClass);
Field idField = vFieldMap.get(idName);
if (idField == null){
throw new IllegalArgumentException("找不到 " + idName + "属性");
}
Field pidField = vFieldMap.get(pidName);
if (pidField == null){
throw new IllegalArgumentException("找不到 " + pidName + "属性");
}
Field childField = vFieldMap.get(childName);
if (childField == null){
throw new IllegalArgumentException("找不到 " + childName + "属性");
}
Map<Object, List<T>> map = new HashMap<>();
for (T t : list) {
Object value = pidField.get(t);
List<T> objects = map.get(value);
if (CollUtil.isEmpty(objects)){
objects = new ArrayList<>();
map.put(value, objects);
}
objects.add(t);
}
List<T> objectList = new ArrayList<>();
List<T> topList = map.get(topValue);
if (CollUtil.isNotEmpty(topList)){
for (T o : topList) {
objectList.add(addChildNode(o, map, idField, childField));
}
}
return objectList;
}
private T addChildNode(T treeNode, Map<Object, List<T>> map, Field idField, Field childField) throws IllegalAccessException {
List<T> objectList = map.get(idField.get(treeNode));
if (CollUtil.isNotEmpty(objectList)){
List<T> treeNodeList = new ArrayList<>();
for (T t : objectList) {
treeNodeList.add(addChildNode(t, map, idField, childField));
}
childField.set(treeNode, treeNodeList);
}
return treeNode;
}
private Map<String, Field> getAllFieldMap(Class<?> cls){
Field[] vFields = getAllFields(cls);
Map<String, Field> fieldMap = new HashMap<>(vFields.length);
for (Field field : vFields) {
field.setAccessible(true);
fieldMap.put(field.getName(), field);
}
return fieldMap;
}
private static Field[] getAllFields(final Class<?> cls) {
final List<Field> allFieldsList = getAllFieldsList(cls);
return allFieldsList.toArray(new Field[0]);
}
private static List<Field> getAllFieldsList(final Class<?> cls) {
if (cls==null){
throw new IllegalArgumentException("The class must not be null");
}
final List<Field> allFields = new ArrayList<>();
Class<?> currentClass = cls;
while (currentClass != null) {
final Field[] declaredFields = currentClass.getDeclaredFields();
allFields.addAll(Arrays.asList(declaredFields));
currentClass = currentClass.getSuperclass();
}
return allFields;
}
@Data
static class MyTree{
private Integer id;
private String name;
private Integer pid;
private List<MyTree> child;
}
public static void main(String[] args) throws IllegalAccessException {
List<MyTree> trees = new ArrayList<>();
for (int i = 1; i < 10; i++) {
MyTree myTree = new MyTree();
myTree.setName("顶级"+i);
myTree.setId(i);
myTree.setPid(0);
trees.add(myTree);
for (int j = 0; j <10 ; j++) {
MyTree myTree1 = new MyTree();
myTree1.setName("子级"+j);
myTree1.setId(j+(i*100));
myTree1.setPid(i);
trees.add(myTree1);
for (int k = 0; k <10 ; k++) {
MyTree myTree2 = new MyTree();
myTree2.setName("子级"+j);
myTree2.setId(k+(j*100)+(i*10000));
myTree2.setPid(j+(i*100));
trees.add(myTree2);
}
}
}
System.out.println(trees.size());
System.out.println("开始生成树");
long l = System.currentTimeMillis();
Collection<MyTree> tree = new TreeUtils<MyTree>().intTree(trees);
long l2 = System.currentTimeMillis();
System.out.println("生成树耗时:" + (l2 - l));
System.out.println(JSON.toJSONString(tree));
}
}