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 }