思路
- 我们首先要知道数据中,哪两列能够体现父子级
- 我们需要找到最顶层父 id 是什么,因为只有知道最顶层的父 id,我们才能进行递归
- 我们要在不改变数据的原有结构下,而转换为 Tree 结构,那么就需要创建新的结构
代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TreeId {}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TreeParentId {}
public class TreeUtils<T> {
private Class<T> aClass;
private Field treeIdField;
private Field treeParentIdField;
private final String CHILDREN_KEY = "children";
public TreeUtils(Class<T> aClass) {
if (aClass == null) {
throw new RuntimeException("传入的class为NULL");
}
this.aClass = aClass;
init();
}
private void init() {
Field[] fields = this.aClass.getDeclaredFields();
for (Field f : fields) {
if (f.isAnnotationPresent(TreeId.class)) {
this.treeIdField = f;
} else if (f.isAnnotationPresent(TreeParentId.class)) {
this.treeParentIdField = f;
}
if (this.treeIdField != null && this.treeParentIdField != null) {
break;
}
}
if (this.treeIdField == null || this.treeParentIdField == null) {
throw new RuntimeException("没有找到相应的注解");
}
this.treeIdField.setAccessible(true);
this.treeParentIdField.setAccessible(true);
}
public List<HashMap<String, Object>> getTreeData(List<T> data) throws IllegalAccessException {
Object topParentId = getTopParentId(data);
return buildTreeData(data, topParentId);
}
private Object getTopParentId(List<T> data) throws IllegalAccessException {
Map<Object, Integer> parentIdMap = new HashMap<>();
for (T o : data) {
Object v = this.treeParentIdField.get(o);
parentIdMap.put(v, 0);
}
for (T o : data) {
Object v = this.treeIdField.get(o);
if (parentIdMap.containsKey(v)) {
int keyValue = parentIdMap.get(v);
parentIdMap.put(v, ++keyValue);
}
}
Object topParentId = null;
Set<Map.Entry<Object, Integer>> entries = parentIdMap.entrySet();
for (Map.Entry<Object, Integer> e : entries) {
if (e.getValue() == 0) {
topParentId = e.getKey();
}
}
return topParentId;
}
private List<HashMap<String, Object>> buildTreeData(List<T> data, Object parentId) throws IllegalAccessException {
List<HashMap<String, Object>> list = new ArrayList<>();
for (T o : data) {
Object pid = this.treeParentIdField.get(o);
Object tid = this.treeIdField.get(o);
if (pid.equals(parentId)) {
HashMap<String, Object> map = new HashMap<>();
Field[] fields = this.aClass.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
map.put(f.getName(), f.get(o));
}
List<HashMap<String, Object>> children = buildTreeData(data, tid);
if (children.size() > 0) {
map.put(CHILDREN_KEY, children);
}
list.add(map);
}
}
return list;
}
}
class TreeUtilsTest {
class Dept {
@TreeId
private int id;
private String deptName;
@TreeParentId
private int parentId;
public Dept(int id, String deptName, int parentId) {
this.id = id;
this.deptName = deptName;
this.parentId = parentId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public int getParentId() {
return parentId;
}
public void setParentId(int parentId) {
this.parentId = parentId;
}
}
class Dept2 {
@TreeId
private String id;
private String deptName;
@TreeParentId
private String parentId;
public Dept2(String id, String deptName, String parentId) {
this.id = id;
this.deptName = deptName;
this.parentId = parentId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
}
@Test
void getTreeData() {
List<Dept2> list = new ArrayList<>();
list.add(new Dept2("1", "闲简居有限公司", "0"));
list.add(new Dept2("2", "开发部", "1"));
list.add(new Dept2("4", "Java组", "2"));
list.add(new Dept2("5", "前端组", "2"));
list.add(new Dept2("3", "测试部", "1"));
TreeUtils<Dept2> treeUtils = new TreeUtils<>(Dept2.class);
List<HashMap<String, Object>> mapList = null;
try {
mapList = treeUtils.getTreeData(list);
} catch (IllegalAccessException e) {
Assertions.fail(e.getMessage());
}
Assertions.assertNotEquals(null, mapList);
System.out.println(mapList);
}
}