【代码这么写】Tree-两行代码返回一颗树
【代码这么写】Tree-两行代码返回一颗树
Last edited 2022-9-28
date
Mar 28, 2021
type
Post
status
Published
slug
dmzmx-tree
summary
概要:lambda表达式+递归实现树的返回,再也不需要嫌拼树麻烦了!
tags
代码实战
category
代码怎么写
password
Property
Sep 28, 2022 06:57 AM
icon

Tree

一、概述

1. 树结构数据

在大家平时的项目开发过程中,经常会遇到一些页面上要分类、分层展示的数据,或者以树的形式展示,如:
京东页面的分类标签
notion image
全国地市县下拉列表
notion image
电子卷宗目录树(网上看到这图片,怀旧的感觉呀,致曾经的电子卷宗团队)
notion image

2. 节点数据要素

树结构表基本字段设计,其中id和pId类型必须相同,也可以换成Long类型
字段名称
字段类型
含义
是否必须
id
String
主键
name
String
名称
order
int
顺序
p_id
String
父节点id

3. 实现方式

  • 后端返回保证保证层级顺序的list平铺数据,由前端组件遍历封装成Tree结构
  • 后端直接返回Tree结构,前端根据树结构数据进行渲染

二、后端返回Tree结构数据

后端小伙伴们,有时候觉得拼装Tree很麻烦,尤其是前后端分离的项目,会选择跟前端小伙伴PK一下,推给前端做。其实更实用的方法还是后端返回Tree结果数据,前端直接用树组件解析渲染。
下面用非常简洁的几行代码,实现后端拼装Tree的过程,小伙伴们不需要再嫌弃拼树麻烦了~!

1. 示例基础类

@Data public class Directory { /** * 主键 */ private String id; /** * 名称 */ private String name; /** * 节点顺序 */ private int order; /** * 父节点id */ private String pId; /** * 子节点list(这个字段拼树结构专用) */ private List<Directory> children; }

2. 树的拼装逻辑

/** * 根据业务Id获取目录结构树 * * @param businessId 业务id * @return list */ public List<Directory> getDirectoryTree(String businessId) { //获取所有directory集合,来源可以是:1 数据库;2 json文件; List<Directory> directories = getAllDirectoriesByBusinessId(businessId); //lambda表达式流式计算 return directories.stream() //过滤器过滤出跟节点,directory.getPId() == null 是条件,按实际情况给条件就行 .filter(directory -> directory.getPId() == null) //拿出根目录,做children节点拼装,getDirectoryChildren 是一个递归函数,下边所有的层级都递归处理了 .peek(rootDirectory -> rootDirectory.setChildren(getDirectoryChildren(rootDirectory, directories))) //排序:按实际情况排 .sorted(Comparator.comparingInt(Directory::getOrder)) //最后转成list .collect(Collectors.toList()); } /** * 递归函数,组装children * * @param parentDirectory 父节点 * @param directories 全量集合 * @return children list */ private List<Directory> getDirectoryChildren(Directory parentDirectory, List<Directory> directories) { return directories.stream() //过滤出parentDirectory的所有子节点 .filter(directory -> directory.getPId().equals(parentDirectory.getId())) //递归setChildren .peek(directory -> directory.setChildren(getDirectoryChildren(directory, directories))) //排序 .sorted(Comparator.comparingInt(Directory::getOrder)) //转list .collect(Collectors.toList()); }

三、结语

怎么样,很简单吧!
Java8 引入的Lambda表达式+递归函数,简单紧凑的两行代码实现了Tree的数据拼装,并且还可以基于stream横向扩展,添加其他业务处理,所以好好学习下Lambda表达式吧!
下边提供一个学习Java Lambda表达式的网站:
 
  • 代码实战
  • 1分钟基于SpringBoot创建后台服务【架构设计】01-重构代码