Java怎么用递归实现树形结构的工具类
需求描述
有时候,我们的数据是带有层级的,比如常见的省市区三级联动,就是一层套着一层,如下图:
而我们在数据库存放数据的时候,往往是列表形式的,如下图:
那么当我们从数据库查询出来,返回给前端的时候,前端又需要给出树形层级的时候,这个时候可能就需要递归处理为树形结构了,因此下面这个工具或许就可以用得上了。
使用示例
我们按照上面定义一个Place对象,打上工具注解:
@TreeKey 标识唯一
@TreeParentKey 标识父节点标识
@TreeChildren 标识子孙节点集合
@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; } }
测试:
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)); } }
最终效果:
工具代码
@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(); } }
以上是Java怎么用递归实现树形结构的工具类的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Java 8引入了Stream API,提供了一种强大且表达力丰富的处理数据集合的方式。然而,使用Stream时,一个常见问题是:如何从forEach操作中中断或返回? 传统循环允许提前中断或返回,但Stream的forEach方法并不直接支持这种方式。本文将解释原因,并探讨在Stream处理系统中实现提前终止的替代方法。 延伸阅读: Java Stream API改进 理解Stream forEach forEach方法是一个终端操作,它对Stream中的每个元素执行一个操作。它的设计意图是处

胶囊是一种三维几何图形,由一个圆柱体和两端各一个半球体组成。胶囊的体积可以通过将圆柱体的体积和两端半球体的体积相加来计算。本教程将讨论如何使用不同的方法在Java中计算给定胶囊的体积。 胶囊体积公式 胶囊体积的公式如下: 胶囊体积 = 圆柱体体积 两个半球体体积 其中, r: 半球体的半径。 h: 圆柱体的高度(不包括半球体)。 例子 1 输入 半径 = 5 单位 高度 = 10 单位 输出 体积 = 1570.8 立方单位 解释 使用公式计算体积: 体积 = π × r2 × h (4

Spring Boot简化了可靠,可扩展和生产就绪的Java应用的创建,从而彻底改变了Java开发。 它的“惯例惯例”方法(春季生态系统固有的惯例),最小化手动设置
