树形结构是我们开发过程中经常遇到的一种数据结构
例如:权限树,菜单树,分类树……
数据表结构
其数据库设计大多如下:
create table sys_menu
(
id varchar(64) primary key not null,
name varchar(64) not null comment '菜单名称',
pid varchar(64) not null default '0' comment '父id'
) comment '系统菜单表';
实体类
@Data
@Accessors(chain = true)
public class SysMenu {
/**
* id
*/
private String id;
/**
* 菜单名称
*/
private String name;
/**
* 父id
*/
private String pid;
}
设计结构
根据数据库可以设计出如下的数据结构
- data: 数据库任意一行数据
- children:data节点下的所有数据集合
即:
/**
* 树形结构模型类
*
* @author zukxu
* @since 2022-1-2-18:09:32
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TreeNode<T> {
/**
* 节点根数据
*/
private T rootNode;
/**
* 节点内容
*/
private List<TreeNode<T>> childrenNode = new ArrayList<>();
工具类-ConvertTree
这是一个将其他的数据转换为Tree的工具类
public class ConvertTree<T> {
}
获取数据
一次性从数据库中获取全部的数据,将取出的数据放入一个list中
每一个节点都应该有获取其子节点的方法
在树形节点类中添加一个方法获取其子节点内容
通过rootNode的id对比相同的放入子节点集合中,不相同的从数据集合中删除,只要集合为空即遍历结束
/**
* 获取子节点
*
* @param dataList 数据集合
* @param idName id字段名
* @param pidName pid字段名
*
* @return 子节点集合
*/
public List<TreeNode<T>> childrenNode(List<T> dataList, String idName, String pidName) {
ConvertTree<T> convertTree = new ConvertTree<>();
String idValue = convertTree.getFieldValue(rootNode, idName);
List<T> collect = dataList.stream()
.filter(t -> idValue.equals(convertTree.getFieldValue(t, pidName))).toList();
dataList.removeAll(collect);
collect.forEach(t -> {
TreeNode<T> treeNode = new TreeNode<>();
treeNode.setRootNode(t);
childrenNode.add(treeNode);
});
return childrenNode;
}
由于无法知道具体的类,也就不知道构建Tree的id字段和pid字段,所以我们可以采用反射的方式获取字段的值