Bean树构建工具-BeanTree
# 📚简介
BeanTree是Hutool树结构模块中用于构建树的工具类,特点是采用Lambda表达式,支持对指定类型的Bean进行树操作。它通过定义Bean的主键、外键、子集等属性,实现了集合到树的转换、树到集合的扁平化、树节点过滤和遍历等功能。
# 🌲核心功能
- 集合转树:将扁平化的Bean集合转换为树结构
- 树转集合:将树结构扁平化为集合
- 树节点过滤:根据条件过滤树节点,保留符合条件的节点及其路径
- 树节点遍历:遍历树中的所有节点
- Lambda支持:采用Lambda表达式,简化开发
- 类型安全:支持泛型,确保类型安全
# 🎯使用场景
- 组织架构管理:将部门集合转换为部门树
- 菜单管理:将菜单集合转换为菜单树
- 分类管理:将商品分类集合转换为分类树
- 权限管理:将权限集合转换为权限树
- 树状数据处理:任何需要处理树状结构数据的场景
# 📋Bean要求
使用BeanTree的Bean需要满足以下条件:
- 包含不为null的主键(例如id)
- 包含允许为null的关联外键(例如parentId)
- 包含自身的子集,例如类型为List的children
# 🚀快速开始
# 定义Bean
// 定义树节点Bean
class Menu {
private Long id;
private Long parentId;
private String name;
private List<Menu> children;
// getter和setter方法
// ...
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Menu> getChildren() {
return children;
}
public void setChildren(List<Menu> children) {
this.children = children;
}
}
# 集合转树
// 准备扁平化数据
List<Menu> menuList = new ArrayList<>();
menuList.add(new Menu(1L, null, "根菜单", null));
menuList.add(new Menu(2L, 1L, "子菜单1", null));
menuList.add(new Menu(3L, 1L, "子菜单2", null));
menuList.add(new Menu(4L, 2L, "子菜单1-1", null));
// 构建BeanTree
BeanTree<Menu, Long> beanTree = BeanTree.of(
Menu::getId, // 主键getter
Menu::getParentId, // 外键getter
null, // 根节点外键值
Menu::getChildren, // 子集getter
Menu::setChildren // 子集setter
);
// 转换为树结构
List<Menu> menuTree = beanTree.toTree(menuList);
# 树转集合
// 将树转换为集合
List<Menu> flatMenuList = beanTree.flat(menuTree);
# 树节点过滤
// 过滤名称包含"子菜单1"的节点及其路径
List<Menu> filteredTree = beanTree.filter(menuTree, menu -> {
return menu.getName().contains("子菜单1");
});
# 树节点遍历
// 遍历树节点
beanTree.forEach(menuTree, menu -> {
Console.log("菜单名称: {}", menu.getName());
});
# 📖方法详解
# of() 静态方法
功能:构建BeanTree实例,使用外键值匹配根节点
参数:
idGetter:主键getterpidGetter:外键getterpidValue:根节点的外键值childrenGetter:子集getterchildrenSetter:子集setter
返回值:BeanTree<T, R> - BeanTree实例
使用示例:
// 使用外键值匹配根节点
BeanTree<Menu, Long> beanTree = BeanTree.of(
Menu::getId, // 主键getter
Menu::getParentId, // 外键getter
null, // 根节点外键值
Menu::getChildren, // 子集getter
Menu::setChildren // 子集setter
);
# ofMatch() 静态方法
功能:构建BeanTree实例,使用条件匹配根节点
参数:
idGetter:主键getterpidGetter:外键getterparentPredicate:根节点匹配条件childrenGetter:子集getterchildrenSetter:子集setter
返回值:BeanTree<T, R> - BeanTree实例
使用示例:
// 使用条件匹配根节点
BeanTree<Menu, Long> beanTree = BeanTree.ofMatch(
Menu::getId, // 主键getter
Menu::getParentId, // 外键getter
menu -> menu.getParentId() == null, // 根节点匹配条件
Menu::getChildren, // 子集getter
Menu::setChildren // 子集setter
);
# toTree(list)
功能:将集合转换为树结构
参数:
list:源数据集合
返回值:List<T> - 树结构列表
使用示例:
// 将集合转换为树
List<Menu> menuTree = beanTree.toTree(menuList);
# flat(tree)
功能:将树结构扁平化为集合
参数:
tree:树结构列表
返回值:List<T> - 扁平化集合
使用示例:
// 将树转换为集合
List<Menu> flatMenuList = beanTree.flat(menuTree);
# filter(tree, condition)
功能:过滤树节点,保留符合条件的节点及其路径
参数:
tree:树结构列表condition:过滤条件
返回值:List<T> - 过滤后的树结构
使用示例:
// 过滤名称包含"子菜单"的节点
List<Menu> filteredTree = beanTree.filter(menuTree, menu -> {
return menu.getName().contains("子菜单");
});
# forEach(tree, action)
功能:遍历树中的所有节点
参数:
tree:树结构列表action:节点处理动作
返回值:List<T> - 原树结构
使用示例:
// 遍历树节点
beanTree.forEach(menuTree, menu -> {
Console.log("菜单: {} - {}", menu.getId(), menu.getName());
});
# 💡注意事项
- 主键非空:Bean的主键必须不为null,否则会抛出异常
- 子集处理:flat方法会将节点的子集合字段置为null
- 过滤逻辑:filter方法会保留符合条件的节点及其完整路径
- 类型安全:确保泛型类型正确,避免类型转换异常
- 性能考虑:对于大型树结构,操作可能影响性能
# 🎨扩展使用
# 复杂条件匹配
// 使用复杂条件匹配根节点
BeanTree<Menu, Long> beanTree = BeanTree.ofMatch(
Menu::getId,
Menu::getParentId,
// 根节点条件:parentId为null且id为1
menu -> menu.getParentId() == null && menu.getId().equals(1L),
Menu::getChildren,
Menu::setChildren
);
# 多级树处理
// 准备多级数据
List<Menu> menuList = new ArrayList<>();
menuList.add(new Menu(1L, null, "一级菜单", null));
menuList.add(new Menu(2L, 1L, "二级菜单1", null));
menuList.add(new Menu(3L, 2L, "三级菜单1-1", null));
menuList.add(new Menu(4L, 3L, "四级菜单1-1-1", null));
menuList.add(new Menu(5L, 1L, "二级菜单2", null));
// 转换为多级树
List<Menu> menuTree = beanTree.toTree(menuList);
# 树节点过滤与遍历结合
// 过滤并遍历树节点
List<Menu> filteredTree = beanTree.filter(menuTree, menu -> {
return menu.getName().contains("菜单1");
});
beanTree.forEach(filteredTree, menu -> {
Console.log("过滤后的菜单: {}", menu.getName());
});
# 📝总结
BeanTree是一个功能强大的树结构处理工具类,采用Lambda表达式,简化了树结构数据的处理。它支持集合转树、树转集合、树节点过滤和遍历等功能,适用于各种树状数据处理场景。通过BeanTree,开发者可以快速构建和操作各类树状结构,提高开发效率。
引用电影经典台词: 无处安放的双手,以及无处安放的灵魂。——《Hello!树先生》