# 树形结构转换工具类 ## 功能介绍 - 将 A类的List数组快速转换为 B类型 List 的树形结构列表 ## 实现原理 - 主要使用到Java反射机制,将A类中的字段拷贝到B类中,并且根据A类中id 与 pid之间的关系快速构建树形结构 - 设置配置类,更方便的实现A类与B类之前转换的需要,配置类包含有id字段与pid字段之间自定义设置,A类中需要转换到B类中的字段,以及是需要Spring 中 BeanUtils直接copy,以及如果使用了BeanUtil后需要排除的字段 ## 代码展示 ```java /** * @author Clay * @date 2022/11/16 */ public class TreeUtil { private static TreeConfig config; private static Class targetClass; /** * 构建tree结构 * * @param list * @param target * @param node * @param * @return */ public static List build(List list, Class target, Node node) { //初始化config config = new TreeConfig(); //将目标class对象设置为全局对象 TreeUtil.targetClass = target; //提供给实现类对config进行修改 node.build(config); //获取到最小的 Object min = list.stream().min(Comparator.comparing(object -> getParentId(object).toString())).get(); //获取到最小的父级id Object minPid = getParentId(min); //将数据通过他们的各自的父id进行分组 Map> listMap = list.stream().collect(Collectors.groupingBy(object -> getParentId(object))); //最终开始进行tree的构建 return getChildren(listMap, minPid); } /** * 获取到子节点 * * @param listMap * @param parentId * @param * @return */ private static List getChildren(Map> listMap, Object parentId) { //获取到缓存中的list List objects = listMap.get(parentId); if (chickList(objects)) { return null; } listMap.remove(parentId); //遍历数组,并将对象一一的转换 List collect = objects.stream().map(object -> conversion(object, listMap)).collect(Collectors.toList()); return (List) collect; } /** * 对象直接的字段进行转换 * * @param object * @param listMap * @param * @return */ private static T conversion(Object object, Map> listMap) { try { Object targetObject = targetClass.newInstance(); //相同字段名称直接赋值 if (config.isCopy()){ BeanUtils.copyProperties(object, targetObject); } //不同字段名进行赋值 for (Map.Entry entry : config.getMapper().entrySet()) { String targetKey = entry.getKey(); String sourceKey = entry.getValue(); Object value = ReflectUtils.invokeGetter(object, sourceKey); Object[] args = new Object[]{value}; ReflectUtils.invokeSetter(targetObject, targetKey, args); } //设置子节点 Object id = ReflectUtils.invokeGetter(object, config.getIdField()); List children = getChildren(listMap, id); if (!chickList(children)) { ReflectUtils.invokeSetter(targetObject, config.getChildrenField(), new Object[]{children}); } //设置完毕后,将需要排除的字段进行置空 for (String key : config.getExclude()) { ReflectUtils.invokeSetNull(targetObject, key); } //返回结果 return (T) targetObject; } catch (Exception e) { throw new RuntimeException(e); } } /** * 检查list是否为空 * * @param objects * @return */ private static boolean chickList(List objects) { return null == objects || objects.isEmpty(); } /** * 获取到父级id * * @param object * @return */ private static Object getParentId(Object object) { try { return ReflectUtils.invokeGetter(object, config.getParentField()); } catch (Exception e) { throw new RuntimeException(e); } } } ``` ## 使用demo ```java @Override public List selectDeptTree(String deptName, Integer state) { List deptList = deptMapper.selectDeptList(deptName, state); return TreeUtil.build(deptList,DeptVo.class,(config)->{ config.setIdField("deptId"); config.setMapper("key","deptId"); config.setExclude("phone"); }); } ```