java 查询树结构数据,无限层级树结构通用方法

ops/2025/1/15 4:41:46/
1、数据库表数据

2、controller层TestTree简单测试
@RestController
@RequestMapping("/test")
public class testTreeController {@Autowiredprivate TestTreeService testTreeService;@GetMapping("/list")public List<TestTree> List(TestTree tree){List<TestTree> testTrees = testTreeService.getTreeList(tree);return testTrees;}
}
3、TestTree实体类
@TableName(value ="test_tree")
@Data
public class TestTree implements TreeNode {/*** id*/@TableIdprivate String id;/*** 父级id*/private String pid;/*** 名称*/private String name;/*** 类型*/private String type;@TableField(exist = false)private static final long serialVersionUID = 1L;@TableField(exist = false)private List childNodeList = new ArrayList<>();@Overridepublic void setChildNodeList(List childNodeList) {this.childNodeList = childNodeList;}@Overridepublic List getChildNodeList() {return childNodeList;}
}
4、TestTreeService 接口
public interface TestTreeService extends IService<TestTree> {/*** 查找树结构List* @param tree 查询条件* @return 树结构结果*/List<TestTree> getTreeList(TestTree tree);
}
5、TestTreeServiceImpl 实现类
@Service
public class TestTreeServiceImpl extends ServiceImpl<TestTreeMapper, TestTree>implements TestTreeService{public List<TestTree> selectList(TestTree tree) {LambdaQueryWrapper<TestTree> queryWrapper = new LambdaQueryWrapper();queryWrapper.eq(ObjectUtil.isNotEmpty(tree.getId()), TestTree::getId, tree.getId());queryWrapper.like(ObjectUtil.isNotEmpty(tree.getName()), TestTree::getName, tree.getName());queryWrapper.like(ObjectUtil.isNotEmpty(tree.getType()), TestTree::getType, tree.getType());return super.list(queryWrapper);}@Overridepublic List<TestTree> getTreeList(TestTree tree) {//查询数据List<TestTree> list  = this.selectList(tree);//封装树结构,通用方法,参数为传入的ListList<TestTree> treeList = TreeList.getTreeList(list);//返回树结构Listreturn  treeList;}
}
6、构建树结构
6.1、定义TreeNode
public interface TreeNode<E extends TreeNode> {/*** 获取节点ID*/String getId();/*** 获取父ID*/String getPid();void setChildNodeList(List<E> childNodeList);/*** 子节点数据*/List<E> getChildNodeList();
}
6.2、构建树结构
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;/*** 处理树形结构的数据*/
public final class TreeList {public static <E extends TreeNode> List<E> getTreeList(List<E> allData){//通过流操作,过滤出所有pid为空或者为null的节点,就是树的顶层节点List<E> topNode = allData.stream().filter(item -> Objects.isNull(item) || StrUtil.isBlank(item.getPid())).collect(Collectors.toList());//移除所有pid为空或为null的节点allData.removeIf(item->Objects.isNull(item) || StrUtil.isBlank(item.getPid()));//将剩余节点按pid分租,结果存储在map中,pid作为键,节点列表作为值Map<String, List<E>> map = allData.stream().collect(Collectors.groupingBy(TreeNode::getPid));//构建树形结构buildTree(topNode,map);//返回顶层节点列表return topNode;}//构建树形结构public static <E extends TreeNode> void buildTree(List<E> topNode, Map<String,List<E>> map){for (E node : topNode) {//遍历顶层节点,如果节点为null,则跳过if (Objects.isNull(node)){continue;}//获取当前节点的idString id = node.getId();//从map中获取其子节点列表List<E> treeNodes = map.get(id);//将其设置为当前节点的子节点列表node.setChildNodeList(treeNodes);//如果当前节点没有子节点,则继续下一个节点if (CollectionUtil.isEmpty(treeNodes)){continue;}//对当前节点的子节点列表递归调用buildTree方法,继续构建树形结构buildTree(treeNodes,map);}}
}
7、postman测试

 结果

[{"id": "1","pid": null,"name": "第一层级","type": "1","childNodeList": [{"id": "2","pid": "1","name": "第二层级","type": "2","childNodeList": [{"id": "3","pid": "2","name": "第三层级","type": "3","childNodeList": [{"id": "4","pid": "3","name": "第四层级","type": "4","childNodeList": [{"id": "5","pid": "4","name": "第五层级","type": "5","childNodeList": null}]}]},{"id": "6","pid": "2","name": "次二层级","type": "6","childNodeList": null}]}]}
]

http://www.ppmy.cn/ops/149911.html

相关文章

【Python】edge-tts :便捷语音合成

edge-tts 是一个功能强大的 Python 库&#xff0c;利用 Microsoft Azure 的云端文本到语音&#xff08;TTS&#xff09;服务&#xff0c;支持多种语言和声音选项&#xff0c;能够生成高质量、自然听感的语音输出。它支持多种音频格式&#xff0c;包括 MP3、WAV 和 OGG&#xff…

深入解析 C++ 类型转换

简介 C 类型转换是开发者必须掌握的重要技能之一, 无论是处理隐式转换还是显式转换, 理解其背后的机制与用法至关重要. 本篇博客旨在从基础到高级全面解析 C 的类型转换, 包括实际开发中的应用场景和性能分析. 自动转换 隐式类型转换 编译器可以在无需明确指示的情况下, 将一…

ue5 GAS 从零开始00

技能属性GAS 技能 属性 创建一个项目c 插件搜索 gameplay 保证这里勾选上 把这三个弄上去 “GameplayAbilities”,“GameplayTags”,“GameplayTasks” 这样就加载了三个模块 一定要先关ue 先关掉ue 生成 如果没编过&#xff0c;你就检查模块名字是不是没写对 一定要…

Python 在 DevOps 与自动化中的应用

随着信息技术的不断发展&#xff0c;DevOps 文化和自动化流程已经成为现代软件开发和运维的核心。DevOps 强调开发和运维团队之间的协作&#xff0c;旨在通过自动化来提升开发、测试、部署、监控和反馈等各个环节的效率。而 Python 作为一门简单、高效且功能强大的编程语言&…

基于知识蒸馏的跨模态目标检测方法总结

ECCV 2022&#xff1a;Cross-modality knowledge distillation network for monocular 3d object detection Teacher模型&#xff1a;基于LiDAR points训练的3D目标检测模型 Student模型&#xff1a;基于Monocular训练的3D目标检测模型 从image或者LiDAR到BEV特征的转换方法&…

【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法,以及自动化实时数据采集

【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法&#xff0c;以及自动化实时数据采集 mmWave Studio提供的功能完全够用了 不用去纠结用DCA1000低延迟、无GUI传数据 速度最快又保证算力无非就是就是Linux板自己写驱动做串口和UDP 做雷达产品应用也不会采用DCA1000的…

晨辉面试抽签和评分管理系统之六:面试答题倒计时

晨辉面试抽签和评分管理系统&#xff08;下载地址:www.chenhuisoft.cn&#xff09;是公务员招录面试、教师资格考试面试、企业招录面试等各类面试通用的考生编排、考生入场抽签、候考室倒计时管理、面试考官抽签、面试评分记录和成绩核算的面试全流程信息化管理软件。提供了考生…

spring mvc源码学习笔记之十

前面的文章介绍了用 WebApplicationInitializer 或者 AbstractAnnotationConfigDispatcherServletInitializer 来代替 web.xml 。 我们学 java web 的时候就知道&#xff0c;servlet 容器会自动加载 web.xml。 那么&#xff0c;疑问就来了&#xff0c;WebApplicationInitialize…