@Service public class BaseTreeService { /** * 集合转树结构 * * @param allList 目标集合 * @param id 节点编号字段名称 * @param parent 父节点编号字段名称 * @param children 子节点集合属性名称 * @param clazz 集合元素类型 * @return 转换后的树形结构 */ public <T> List<T> listTreeNodes(String id, String parent, String children, List<T> allList, Class<T> clazz) { // 如果被依赖字段名称为空则默认为id if (StringUtils.isEmpty(id)) { id = "id"; } // 如果依赖字段为空则默认为parent if (StringUtils.isEmpty(parent)) { parent = "pid"; } // 如果子节点集合属性名称为空则默认为children if (StringUtils.isEmpty(children)) { children = "children"; } try { // 获取 id 字段, 从当前对象或其父类 Field idField; try { idField = clazz.getDeclaredField(id); } catch (NoSuchFieldException e1) { idField = clazz.getSuperclass().getDeclaredField(id); } // 获取 parentId 字段, 从当前对象或其父类 Field parentField; try { parentField = clazz.getDeclaredField(parent); } catch (NoSuchFieldException e1) { parentField = clazz.getSuperclass().getDeclaredField(parent); } // 获取 children 字段, 从当前对象或其父类 Field childrenField; try { childrenField = clazz.getDeclaredField(children); } catch (NoSuchFieldException e1) { childrenField = clazz.getSuperclass().getDeclaredField(children); } // 设置为可访问 idField.setAccessible(true); parentField.setAccessible(true); childrenField.setAccessible(true); //根节点 List<T> roots = new ArrayList<>(); // 找出所有的根节点 for (T c : allList) { Object parentId = parentField.get(c); if (isRootNode(parentId)) { roots.add(c); } } // 从目标集合移除所有根节点 allList.removeAll(roots); // 遍历根节点, 依次添加子节点 for (T root : roots) { addChild(root, allList, idField, parentField, childrenField); } // 关闭可访问 idField.setAccessible(false); parentField.setAccessible(false); childrenField.setAccessible(false); return roots; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 判断是否是根节点, 判断方式为: 父节点编号为空或为 0, 则认为是根节点. 此处的判断应根据自己的业务数据而定. * * @param parentId 父节点编号 * @return 是否是根节点 */ private boolean isRootNode(Object parentId) { boolean flag = false; if (parentId == null) { flag = true; } else if (parentId instanceof String && (StringUtils.isEmpty(parentId) || parentId.equals("0"))) { flag = true; } else if (parentId instanceof Integer && Integer.valueOf(0).equals(parentId)) { flag = true; } return flag; } /** * 为目标节点添加孩子节点 * * @param node 目标节点 * @param idField ID 字段 * @param parentField 父节点字段 * @param childrenField 字节点字段 */ private <T> void addChild(T node, List<T> list, Field idField, Field parentField, Field childrenField) throws IllegalAccessException { Object id = idField.get(node); List<T> children = (List<T>) childrenField.get(node); // 如果子节点的集合为 null, 初始化孩子集合 // 如果子节点的集合为 null, 初始化孩子集合 if (children == null) { children = new ArrayList<>(); } for (T t : list) { Object o = parentField.get(t); if (id.equals(o)) { // 将当前节点添加到目标节点的孩子节点 children.add(t); // 重设目标节点的孩子节点集合,这里必须重设,因为如果目标节点的孩子节点是null的话,这样是没有地址的,就会造成数据丢失,所以必须重设,如果目标节点所在类的孩子节点初始化为一个空集合,而不是null,则可以不需要这一步,因为java一切皆指针 childrenField.set(node, children); // 递归添加孩子节点 addChild(t, list, idField, parentField, childrenField); } } } }
//调用
List<Dept> newDeptList = listTreeNodes("deptId", "pid", "children", deptList, Dept.class);