思路
- 我们首先要知道数据中,哪两列能够体现父子级
- 我们需要找到最顶层父 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 {@TreeIdprivate int id;private String deptName;@TreeParentIdprivate 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 {@TreeIdprivate String id;private String deptName;@TreeParentIdprivate 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;}}@Testvoid 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);}
}