java
复制代码
public class TreeBuilder<T> {
public List<T> buildTree(List<T> nodes) throws Exception {
if (nodes == null || nodes.isEmpty()) return Collections.emptyList();
Class<?> clazz = nodes.get(0).getClass();
Field idField = getFieldWithAnnotation(clazz, TreeId.class);
Field parentIdField = getFieldWithAnnotation(clazz, TreeParentId.class);
Field childrenField = getChildrenField(clazz);
idField.setAccessible(true);
parentIdField.setAccessible(true);
if (childrenField != null) childrenField.setAccessible(true);
// 建立id到node的映射
Map<Object, T> idMap = new HashMap<>();
for (T node : nodes) {
Object id = idField.get(node);
idMap.put(id, node);
}
List<T> roots = new ArrayList<>();
for (T node : nodes) {
Object parentId = parentIdField.get(node);
if (!idMap.containsKey(parentId) || parentId == null || "".equals(parentId)) {
roots.add(node);
} else {
T parent = idMap.get(parentId);
if (childrenField != null) {
List<T> children = (List<T>) childrenField.get(parent);
if (children == null) {
children = new ArrayList<>();
childrenField.set(parent, children);
}
children.add(node);
}
}
}
return roots;
}
private Field getFieldWithAnnotation(Class<?> clazz, Class<? extends java.lang.annotation.Annotation> anno) {
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(anno)) return f;
}
throw new IllegalArgumentException("No field with annotation " + anno);
}
private Field getChildrenField(Class<?> clazz) {
for (Field f : clazz.getDeclaredFields()) {
if ("children".equals(f.getName())) return f;
}
return null;
}
/**
* 集合构建树形结构
* 1.数据节点,父级id不存在集合中,则需要将父级节点设置为根节点
* @param nodes
* @param rootId
* @return
*/
public static List<WisDepartment> buildTree(List<WisDepartment> nodes,String rootId) {
Map<String, WisDepartment> idNodeMap = nodes.stream()
.collect(Collectors.toMap(WisDepartment::getExternalId, node -> node));
List<WisDepartment> rootNodes = new ArrayList<>();
for (WisDepartment node : nodes) {
if (rootId.equals(node.getExternalParentId())) {
// 根节点
rootNodes.add(node);
} else {
// 非根,根据parentId 找父节点,然后把自己加入父节点的children
WisDepartment parent = idNodeMap.get(node.getExternalParentId());
if (parent != null) {
parent.getChildren().add(node);
}else{
node.setExternalParentId(rootId);
rootNodes.add(node);
}
}
}
return rootNodes;
}
public static void main(String[] args) throws Exception {
List<WisDepartment> departments = JSONArray.parseArray(ss,WisDepartment.class);
System.out.println("data1: "+ JSONObject.toJSONString(departments));
String rootId = "20221206140844614-6ECD-5B3376E42";
TreeBuilder<WisDepartment> builder = new TreeBuilder<>();
// List<WisDepartment> tree = builder.buildTree(departments);
List<WisDepartment> tree2 = builder.buildTree(departments,rootId);
//
//
// List<WisDepartment> collect = departments.stream().filter(m -> m.getExternalParentId().equals(rootId)).map(
// (m) -> {
// m.setChildren(getChildrenList(m, departments));
// return m;
// }
// ).collect(Collectors.toList());
// System.out.println(JSONObject.toJSONString(collect));
System.out.println("data2: "+JSONObject.toJSONString(departments));
}
/**
* 获取子节点列表
* @param tree
* @param list
* @return
*/
public static List<WisDepartment> getChildrenList(WisDepartment tree, List<WisDepartment> list){
List<WisDepartment> children = list.stream().filter(item -> item.getExternalParentId().equals( tree.getExternalId())).map(
(item) -> {
item.setChildren(getChildrenList(item, list));
return item;
}
).collect(Collectors.toList());
return children;
}
public static String ss = "[\n" +
" {\n" +
" \"an_org_id\": \"an001\",\n" +
" \"externalId\": \"an001\",\n" +
" \"parent_id\": \"20221206140844614-6ECD-5B3376E42\",\n" +
" \"externalParentId\": \"20221206140844614-6ECD-5B3376E42\",\n" +
" \"path\": \"父组织路径\",\n" +
" \"path_name\": \"组织全路径名称\",\n" +
" \"org_level\": \"1\",\n" +
" \"org_name\": \"an001bbk\",\n" +
" \"org_name_abbr\": \"组织简称\",\n" +
" \"org_order\": \"1\",\n" +
" \"an_org_type\": \"1\",\n" +
" \"an_credit_code\": \"xfn40\",\n" +
" \"an_legal_person\": \"法定代表人\",\n" +
" \"sys_org_code\": \"创建人所属部门\",\n" +
" \"org_is_disabled\": \"0\",\n" +
" \"postal_address\": \"通讯地址(公司/基地)\",\n" +
" \"charge_project_name\": \"项目部负责人\"\n" +
" }, \n" +
"\t\t{\n" +
" \"an_org_id\": \"an002\",\n" +
" \"externalId\": \"an002\",\n" +
" \"parent_id\": \"20221206140844614-6ECD-5B3376E42\",\n" +
" \"externalParentId\": \"20221206140844614-6ECD-5B3376E42\",\n" +
" \"path\": \"父组织路径\",\n" +
" \"path_name\": \"组织全路径名称\",\n" +
" \"org_level\": \"1\",\n" +
" \"org_name\": \"an002\",\n" +
" \"org_name_abbr\": \"组织简称\",\n" +
" \"org_order\": \"2\",\n" +
" \"an_org_type\": \"1\",\n" +
" \"an_credit_code\": \"xfn40\",\n" +
" \"an_legal_person\": \"法定代表人\",\n" +
" \"sys_org_code\": \"创建人所属部门\",\n" +
" \"org_is_disabled\": \"0\",\n" +
" \"postal_address\": \"通讯地址(公司/基地)\",\n" +
" \"charge_project_name\": \"项目部负责人\"\n" +
" }, \n" +
"\t\t{\n" +
" \"an_org_id\": \"an001001\",\n" +
" \"externalId\": \"an001001\",\n" +
" \"parent_id\": \"an002\",\n" +
" \"externalParentId\": \"an002\",\n" +
" \"path\": \"父组织路径\",\n" +
" \"path_name\": \"组织全路径名称\",\n" +
" \"org_level\": \"1\",\n" +
" \"org_name\": \"an001001\",\n" +
" \"org_name_abbr\": \"组织简称\",\n" +
" \"org_order\": \"1\",\n" +
" \"an_org_type\": \"1\",\n" +
" \"an_credit_code\": \"xfn40\",\n" +
" \"an_legal_person\": \"法定代表人/负责人\",\n" +
" \"sys_org_code\": \"创建人所属部门\",\n" +
" \"org_is_disabled\": \"0\",\n" +
" \"postal_address\": \"通讯地址(公司/基地)\",\n" +
" \"charge_project_name\": \"项目部负责人\"\n" +
" }\n" +
"\t\t, \n" +
"\t\t{\n" +
" \"an_org_id\": \"an003\",\n" +
" \"externalId\": \"an003\",\n" +
" \"parent_id\": \"an003\",\n" +
" \"externalParentId\": \"an0039\",\n" +
" \"path\": \"父组织路径\",\n" +
" \"path_name\": \"组织全路径名称\",\n" +
" \"org_level\": \"1\",\n" +
" \"org_name\": \"an003\",\n" +
" \"org_name_abbr\": \"组织简称\",\n" +
" \"org_order\": \"1\",\n" +
" \"an_org_type\": \"1\",\n" +
" \"an_credit_code\": \"xfn40\",\n" +
" \"an_legal_person\": \"法定代表人/负责人\",\n" +
" \"sys_org_code\": \"创建人所属部门\",\n" +
" \"org_is_disabled\": \"0\",\n" +
" \"postal_address\": \"通讯地址(公司/基地)\",\n" +
" \"charge_project_name\": \"项目部负责人\"\n" +
" }\n" +
" ]";
}