持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
在日常的开发过程中树状结构我们进行用到的,比如部门表就需要我们用到返回部门树的结构类型,一般可以前端生成也可以后端返回生成好的树形结构,最常用的就是采用递归的方式生成一个树形结构,这样的代码不够简洁与完整,下面来看看如何3行代码生成一个树形结构图,来缩减代码。
定义一个Menu的类,定义返回的实体类。
public class Menu {
private String id;
private String parentId;
private String name;
private Integer weight;
private List<Menu> childrenMenu;
public Menu(String id, String parentId, String name, Integer weight) {
this.id = id;
this.parentId = parentId;
this.name = name;
this.weight = weight;
}
}
模拟从数据库查询返回的数据
// 构建node列表
List<Menu> nodeList = CollUtil.newArrayList();
// 模拟从数据库返回的数据
nodeList.add(new Menu("1", "0", "系统管理", 1));
nodeList.add(new Menu("2", "1", "用户管理", 1));
nodeList.add(new Menu("3", "1", "角色添加", 2));
nodeList.add(new Menu("7", "2", "用户添加", 1));
nodeList.add(new Menu("4", "0", "店铺管理", 2));
nodeList.add(new Menu("5", "4", "名称管理", 1));
nodeList.add(new Menu("6", "4", "商品管理", 2));
使用Java8的新特性
- 对非父节点的数据按照parentId进行分组。
- 对原来数据进行插入childrenMenu,按照父节点取分组后的值。
- 过滤掉非父节点的数据进行输出。
@GetMapping("getTree")
public List<Menu> getTree(){
Map<String, List<Menu>> collect = nodeList.stream().filter(menu -> !"0".equals(menu.getParentId())).collect(Collectors.groupingBy(Menu::getParentId));
nodeList.forEach(menu -> menu.setChildrenMenu(collect.get(menu.getId())));
List<Menu> menus = nodeList.stream().filter(menu -> "0".equals(menu.getParentId())).collect(Collectors.toList());
return menus;
}
返回结果如下所示,构建好了树形的结构数据返回。对于这三行代码也可以封装成工具类进行使用,不过hutool由封装的工具类并且支持更加复杂的数据结构。
hutool返回树形结构数据
@GetMapping("test1")
public List<Tree<String>> test1() {
//配置 主要配置父节点,和字节的的id,默认是id,parnentId
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
// 自定义属性名 都要默认值的
// weight小的在前面
treeNodeConfig.setWeightKey("weight");
treeNodeConfig.setIdKey("id");
treeNodeConfig.setParentIdKey("parentId");
// 最大递归深度
treeNodeConfig.setDeep(3);
//转换器
List<Tree<String>> treeNodes = TreeUtil.build(nodeList, "0", treeNodeConfig,
(treeNode, tree) -> {
tree.setId(treeNode.getId());
tree.setParentId(treeNode.getParentId());
tree.setWeight(treeNode.getWeight());
tree.setName(treeNode.getName());
// 扩展属性 ...
tree.putExtra("extraField", 666);
});
return treeNodes;
}
优点:hutool的TreeUtil构建树形状定制化更高,它提供了一个配置类来配置树形结构数据,即使父节点ID和子节点ID不一样都能通过配置类来实现。而且提供扩展属性,可以展示非该List集合下的数据。在对树的递归深度也可以通过配置来实现。
补充
在数据库设计的使用对于树结构数据我们通常在一张表里面使用两个字段id,和parentId进行设计,这样可以精简数据库表的设计。