Sometimes, our data is hierarchical. For example, the common three-level linkage between provinces and municipalities is one layer inside another, as shown below:
When we store data in the database, it is often in list form, as shown below:
Then when we query it from the database, When returning to the front end, when the front end needs to give a tree level, it may need to be recursively processed into a tree structure, so the following tool may be useful.
We define a Place object as above and add tool annotations:
@TreeKey unique identifier
@TreeParentKey identifies the parent node identification
@TreeChildren identifies the collection of descendant nodes
@Data @Data public class Place { @TreeKey private String id; @TreeParentKey private String parentId; private String name; @TreeChildren private List<Place> children; public Place(String id, String name, String parentId) { this.id = id; this.name = name; this.parentId = parentId; } }
Test:
public class Test { public static void main(String[] args) { List<Place> places = new ArrayList<>(); places.add(new Place("510000", "四川省", "0")); places.add(new Place("510100", "成都市", "510000")); places.add(new Place("510107", "武侯区", "510100")); places.add(new Place("510116", "双流区", "510100")); places.add(new Place("511600", "广安市", "510000")); places.add(new Place("511603", "前锋区", "511600")); places.add(new Place("511621", "岳池县", "511600")); List<Place> treeList = TreeUtils.getTree(places, "0"); System.out.println(JSON.toJSONString(treeList)); } }
Final effect:
@TreeKey
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface TreeKey { }
@TreeParentKey
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface TreeParentKey { }
@TreeChildren
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface TreeChildren { }
@TreeUtils
package com.csd.utils.tree; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; /** * 递归求树形工具类 * * @author Yuanqiang.Zhang * @since 2023/3/8 */ public class TreeUtils { /** * 集合转化为树形 * * @param list 集合 * @param highestParentKey 最高层父节点值 * @param <T> 泛型 * @return 树形 */ public static <T> List<T> getTree(List<T> list, Object highestParentKey) { if (Objects.isNull(list) || list.isEmpty()) { return Collections.emptyList(); } Field key = null; Field parentKey = null; Field children = null; Field[] fields = list.get(0).getClass().getDeclaredFields(); for (Field field : fields) { if (Objects.isNull(key)) { TreeKey treeKey = field.getAnnotation(TreeKey.class); if (Objects.nonNull(treeKey)) { key = field; continue; } } if (Objects.isNull(parentKey)) { TreeParentKey treeParentKey = field.getAnnotation(TreeParentKey.class); if (Objects.nonNull(treeParentKey)) { parentKey = field; continue; } } if (Objects.isNull(children)) { TreeChildren treeChildren = field.getAnnotation(TreeChildren.class); if (Objects.nonNull(treeChildren)) { children = field; continue; } } } if (Objects.isNull(key) || Objects.isNull(parentKey) || Objects.isNull(children)) { return Collections.emptyList(); } key.setAccessible(true); parentKey.setAccessible(true); children.setAccessible(true); // 获取最高层数据 List<T> highs = new ArrayList<>(); try { for (T t : list) { Object pk = parentKey.get(t); if (getString(pk).equals(getString(highestParentKey))) { highs.add(t); } } // 获取最高层子孙节点 for (T t : highs) { setChildren(list, t, key, parentKey, children); } } catch (IllegalAccessException e) { e.printStackTrace(); } return highs; } /** * 获取子孙节点 * * @param list 集合 * @param parent 父节点对象 * @param key 唯一属性 * @param parentKey 父唯一属性 * @param children 节点 * @param <T> 泛型 * @return 带有子孙集合的父节点对象 * @throws IllegalAccessException */ private static <T> T setChildren(List<T> list, T parent, Field key, Field parentKey, Field children) throws IllegalAccessException { Object k = key.get(parent); List<T> tempList = new ArrayList<>(); for (T t : list) { Object pk = parentKey.get(t); if (getString(k).equals(getString(pk))) { tempList.add(setChildren(list, t, key, parentKey, children)); } } children.set(parent, tempList); return parent; } /** * 获取字符串 * * @param o 值 * @return 字符串 */ private static String getString(Object o) { return Objects.isNull(o) ? "" : o.toString(); } }
The above is the detailed content of How to use recursion to implement a tree structure tool class in Java. For more information, please follow other related articles on the PHP Chinese website!