生成树的工具类

 1 1、 这里使用的是三个注解
 2 
 3 @Target(ElementType.FIELD)
 4 @Retention(RetentionPolicy.RUNTIME)
 5 public @interface TreeId {
 6 }
 7 
 8 @Target(ElementType.FIELD)
 9 @Retention(RetentionPolicy.RUNTIME)
10 public @interface TreeParentId {
11 }
12 
13 @Target(ElementType.FIELD)
14 @Retention(RetentionPolicy.RUNTIME)
15 public @interface TreeChildrenList {
16 }

 

  1 2.  对应的工具类
  2 
  3 /**
  4  * @author: 
  5  * @desc: 将数据组合成一棵树,
  6  * 添加三个注解到   @TreeId   @TreeParentId  @TreeChildrenList
  7  * 这三个注解分别表示 当前数据的 id  当前数据的上级数据id  存放当前数据的子节点集合
  8  **/
  9 public class TreeUtils {
 10 
 11     /**
 12      * 构建树状结构
 13      *
 14      * @param list  原数据集
 15      * @param clazz 数据实体
 16      * @param <T>   泛型
 17      * @return 树状结构
 18      */
 19     public static <T> List<T> buildTree(List<T> list, @NotNull Class clazz) {
 20         RequiredField requiredField = new RequiredField(clazz);
 21         if (CollectionUtil.isEmpty(list) || ObjectUtil.isEmpty(requiredField)) {
 22             return null;
 23         }
 24         // 判断 获取最上级数据的 id
 25         List<Long> rootIdList = new ArrayList<>();
 26         for (T entity : list) {
 27             try {
 28                 Object parentIdValue = requiredField.getParentId().get(entity);
 29                 if (ObjectUtil.isEmpty(parentIdValue) || parentIdValue.equals(0)) {
 30                     rootIdList.add((long) requiredField.getId().get(entity));
 31                 }
 32             } catch (IllegalAccessException e) {
 33                 throw new CustomException("构建树失败,请检查");
 34             }
 35         }
 36         if (CollectionUtil.isEmpty(rootIdList)) {
 37             throw new CustomException("传递进来的数据不存在最上级节点,请检查!");
 38         }
 39 
 40         return buildTree(list, clazz, rootIdList);
 41     }
 42 
 43     /**
 44      * 构建树状结构
 45      *
 46      * @param list     原数据集
 47      * @param parentId 父级字段名
 48      * @param id       id字段名
 49      * @param children 子级字段名
 50      * @param clazz    数据实体
 51      * @param <T>      泛型
 52      * @return 树状结构
 53      */
 54     public static <T> List<T> buildTree(List<T> list, String parentId, String id, String children, @NotNull Class clazz) {
 55         RequiredField requiredField = new RequiredField(id, parentId, children, clazz);
 56         if (CollectionUtil.isEmpty(list) || ObjectUtil.isEmpty(requiredField)) {
 57             return null;
 58         }
 59         // 判断判断 获取最上级数据的 id
 60         List<Long> rootIdList = new ArrayList<>();
 61         for (T entity : list) {
 62             try {
 63                 Object parentIdValue = requiredField.getParentId().get(entity);
 64                 if (ObjectUtil.isEmpty(parentIdValue) || parentIdValue.equals(0)) {
 65                     rootIdList.add((long) requiredField.getId().get(entity));
 66                 }
 67             } catch (IllegalAccessException e) {
 68                 throw new CustomException("构建树失败,请检查");
 69             }
 70         }
 71         if (CollectionUtil.isEmpty(rootIdList)) {
 72             throw new CustomException("传递进来的数据不存在最上级节点,请检查!");
 73         }
 74 
 75         return buildTree(list, clazz, rootIdList);
 76     }
 77 
 78     /**
 79      * 获取指定指点下面的数据 返回的是数据集合。不是树
 80      *
 81      * @param list  原始数据
 82      * @param clazz 数据实体类
 83      * @param id    数据id
 84      * @param <T>   泛型
 85      * @return 返回结果
 86      */
 87     public static <T> List<T> getListById(List<T> list, @NotNull Class clazz, @NotNull Long id, boolean containCurrentNode) {
 88         List<Long> treeIdList = new ArrayList<>();
 89         treeIdList.add(id);
 90 
 91         List<T> chidrenList = new ArrayList<>();
 92         List<T> treeList = TreeUtils.buildTree(list, clazz, treeIdList);
 93         for (T tree : treeList) {
 94             if (ObjectUtil.isNotEmpty(tree)) {
 95                 chidrenList.addAll(getChidrenList(tree, clazz));
 96             }
 97         }
 98         if (containCurrentNode && CollectionUtil.isNotEmpty(chidrenList)) {
 99             chidrenList.addAll(treeList);
100         }
101         return chidrenList;
102     }
103 
104     /**
105      * 获取某个树下面的所有子节点
106      *
107      * @param root  树节点
108      * @param clazz 数据实体
109      * @param <T>   泛型
110      * @return 返回子集合
111      */
112     private static <T> List<T> getChidrenList(T root, @NotNull Class clazz) {
113         List<T> resultList = new ArrayList<>();
114         RequiredField requiredField = new RequiredField(clazz);
115         Field childrenField = requiredField.getChildrenList();
116         try {
117             List<T> childrenList = (List<T>) childrenField.get(root);
118             for (T entity : childrenList) {
119                 if (ObjectUtil.isNotEmpty(entity)) {
120                     resultList.addAll(getChidrenList(entity, clazz));
121                 }
122             }
123             resultList.addAll(childrenList);
124         } catch (IllegalAccessException e) {
125             throw new CustomException("构建树失败,请检查!");
126         }
127         return resultList;
128     }
129 
130 
131     /**
132      * 构建树形状,获取当前id下面的树接待,包括当前节点
133      *
134      * @param list       原数据集
135      * @param clazz      数据实体
136      * @param treeIdList 当前id
137      * @param <T>        数据类型
138      * @return 树形状结构
139      */
140     public static <T> List<T> buildTree(List<T> list, @NotNull Class clazz, List<Long> treeIdList) {
141         RequiredField requiredField = new RequiredField(clazz);
142         if (CollectionUtil.isEmpty(list) || ObjectUtil.isEmpty(requiredField) || CollectionUtil.isEmpty(treeIdList)) {
143             return null;
144         }
145         List<T> resultList = new ArrayList<>(treeIdList.size());
146         try {
147             Iterator<T> iterator = list.iterator();
148             while (iterator.hasNext()) {
149                 T next = iterator.next();
150                 Object idValue = requiredField.getId().get(next);
151                 if (treeIdList.contains(idValue)) {
152                     resultList.add(next);
153                     iterator.remove();
154                     continue;
155                 }
156             }
157             if (CollectionUtil.isEmpty(resultList)) {
158                 throw new CustomException("集合中不存在要查询的数据");
159             }
160             for (T root : resultList) {
161                 requiredField.getChildrenList().set(root, findChild(root, list, requiredField.getParentId(), requiredField.getId(), requiredField.getChildrenList()));
162             }
163         } catch (IllegalAccessException e) {
164             throw new CustomException("构建树失败,请检查");
165         }
166         return resultList;
167     }
168 
169     /**
170      * 构建树状结构
171      *
172      * @param list          数据集
173      * @param parentField   父级ID字段
174      * @param idField       id字段
175      * @param childrenField 子集字段
176      * @param <T>           数据类型
177      * @return 树状结构
178      * @throws IllegalAccessException 异常
179      */
180     public static <T> List<T> buildTree(List<T> list, Field parentField, Field idField, Field childrenField) {
181         List<T> result = new ArrayList<>();
182 
183         try {
184             Iterator<T> iterator = list.iterator();
185             while (iterator.hasNext()) {
186                 T root = iterator.next();
187                 iterator.remove();
188                 childrenField.set(root, findChild(root, list, parentField, idField, childrenField));
189                 // 刷新 iterator
190                 iterator = list.iterator();
191                 result.add(root);
192             }
193         } catch (IllegalAccessException e) {
194             throw new CustomException("构建树失败,请检查");
195         }
196         return result;
197     }
198 
199     /**
200      * 查找子集
201      *
202      * @param root          节点
203      * @param list          所有集合
204      * @param parentField   父级字段
205      * @param idField       id字段
206      * @param childrenField 子级字段
207      * @param <T>
208      * @return 子级集合
209      * @throws IllegalAccessException 异常信息
210      */
211     private static <T> List<T> findChild(T root, List<T> list, Field parentField, Field idField, Field childrenField)
212             throws IllegalAccessException {
213         Object id = idField.get(root);
214         if (ObjectUtil.isEmpty(id)) {
215             throw new CustomException("类中存在相同字段,请检查!");
216         }
217         List<T> children = new ArrayList<>();
218 
219         Iterator<T> iterator = list.iterator();
220         while (iterator.hasNext()) {
221             T node = iterator.next();
222             Object parentId = parentField.get(node);
223 
224             if (id.equals(parentId)) {
225                 iterator.remove();
226                 childrenField.set(node, findChild(node, list, parentField, idField, childrenField));
227                 // 刷新 iterator
228                 iterator = list.iterator();
229                 children.add(node);
230             }
231         }
232         return children;
233     }
234 }
235 
236 /**
237  * 必填字段
238  */
239 class RequiredField {
240     private Field id;
241     private Field parentId;
242     private Field childrenList;
243 
244     public RequiredField(@NotNull Class clazz) {
245         //1 获取类中是否拥有需要的三个注解
246         List<Field> fieldList = ReflectUtils.getAllField(clazz);
247         for (Field field : fieldList) {
248             if (ObjectUtil.isNotEmpty(field.getAnnotation(TreeId.class))) {
249                 this.id = field;
250                 this.id.setAccessible(true);
251             }
252             if (ObjectUtil.isNotEmpty(field.getAnnotation(TreeParentId.class))) {
253                 this.parentId = field;
254                 this.parentId.setAccessible(true);
255             }
256             if (ObjectUtil.isNotEmpty(field.getAnnotation(TreeChildrenList.class))) {
257                 this.childrenList = field;
258                 this.childrenList.setAccessible(true);
259             }
260         }
261     }
262 
263     public RequiredField(String idField, String parentIdField, String childrenListField, @NotNull Class clazz) {
264         // 判断传入字段是否为空
265         if (StrUtil.isEmpty(idField) || StrUtil.isEmpty(parentIdField) || StrUtil.isEmpty(childrenListField)) {
266             throw new CustomException("必填字段不能为空!");
267         }
268         try {
269             // 获取 id 字段, 从当前对象或其父类
270             this.id = clazz.getDeclaredField(idField);
271             this.id.setAccessible(true);
272             // 获取 parentId 字段, 从当前对象或其父类
273             this.parentId = clazz.getDeclaredField(parentIdField);
274             this.parentId.setAccessible(true);
275             // 获取 children 字段, 从当前对象或其父类
276             this.childrenList = clazz.getDeclaredField(childrenListField);
277             this.childrenList.setAccessible(true);
278         } catch (NoSuchFieldException e1) {
279             throw new CustomException("获取字段失败", e1);
280         }
281     }
282 
283     public Field getId() {
284         return id;
285     }
286 
287     public Field getParentId() {
288         return parentId;
289     }
290 
291     public Field getChildrenList() {
292         return childrenList;
293     }
294 }

 

posted @ 2022-07-12 10:48  烟雨蒙尘  阅读(63)  评论(0编辑  收藏  举报