构建树形结构
废话少说,直接上代码
方式一
1、定义实体类
public class Category {
private Long id;
private String name;
private Long parentId;
private List<Category> children;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public List<Category> getChildren() {
return children;
}
public void setChildren(List<Category> children) {
this.children = children;
}
public Category(Long id, String name, Long parentId) {
this.id = id;
this.name = name;
this.parentId = parentId;
}
}
工具类
private static List<Category> categories = new ArrayList<>();
static {
// 绑定初始化一个Category的数据
categories.add(new Category(1L, "一级分类-1", null));
categories.add(new Category(2L, "一级分类-1-1", 1L));
categories.add(new Category(3L, "一级分类-1-2", 1L));
categories.add(new Category(30L, "一级分类-1-2-1", 3L));
categories.add(new Category(4L, "一级分类-2", null));
categories.add(new Category(5L, "一级分类-2-1", 4L));
categories.add(new Category(6L, "一级分类-3", null));
categories.add(new Category(7L, "一级分类-3-1", 6L));
// 子节点
}
public static void main(String[] args) {
String treeJson = JSONUtil.toJsonPrettyStr(parentList01());
System.out.println(treeJson);
}
private static List<Category> parentList01(){
List<Category> parentList = categories.stream().filter(category -> category.getParentId() == null).collect(Collectors.toList());
for (Category category : parentList) {
category.setChildren(buildChildren(category.getId(),categories));
}
return parentList;
}
private static List<Category> buildChildren(Long id, List<Category> categories) {
List<Category> children = new ArrayList<>();
for (Category category : categories) {
if (category.getParentId() == null){
continue;
}
if (category.getParentId().equals(id)){
children.add(category);
}
}
for (Category child : children) {
child.setChildren(buildChildren(child.getId(),categories));
}
return children;
}
方式二
利用Map集合
@Override
public Result currentLeftMenu() {
// 获取认证主体
Subject subject = SecurityUtils.getSubject();
ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
Integer userId = activeUser.getSysUser().getId();
// 根据用户ID 和 菜单权限查询 权限
List<SysPermissionVO> sysPermissionVOS = sysPermissionMapper.selectUserPermission(userId, Constant.PERMISSION_TYPE_MENU);
// 菜单容器
Map<Integer, SysPermissionVO> menu = new HashMap<>();
for (SysPermissionVO sysPermissionVO : sysPermissionVOS) {
// 获取菜单中的父ID
Integer parentId = sysPermissionVO.getParentId();
// 判断父ID是否是一级菜单
if (parentId.equals(Constant.MENU_LV1)) {
sysPermissionVO.setChildren(new ArrayList<SysPermissionVO>());
// key 菜单的ID value
menu.put(sysPermissionVO.getId(), sysPermissionVO);
}
}
// 给1一级菜单赋二级菜单
for (SysPermissionVO sysPermissionVO : sysPermissionVOS) {
Integer parentId = sysPermissionVO.getParentId();
if (menu.containsKey(parentId)) {
SysPermissionVO sysPermissionVO1 = menu.get(parentId);
sysPermissionVO1.getChildren().add(sysPermissionVO);
}
}
Collection<SysPermissionVO> values = menu.values();
// 返回给controller
return new Result(values);
}
方式三:stream流方式
public List<CategoryEntity> listWithTree() {
//1、查出所有分类
List<CategoryEntity> entities = baseMapper.selectList(null);
//2、组装成父子的树形结构
//2.1)、找到所有的一级分类,给children设置子分类
return entities.stream()
// 过滤找出一级分类
.filter(categoryEntity -> categoryEntity.getParentCid() == 0)
// 处理,给一级菜单递归设置子菜单
.peek(menu -> menu.setChildren(getChildless(menu, entities)))
// 按sort属性排序
.sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
.collect(Collectors.toList());
}
/**
* 递归查找所有菜单的子菜单
*/
private List<CategoryEntity> getChildless(CategoryEntity root, List<CategoryEntity> all) {
return all.stream()
.filter(categoryEntity -> categoryEntity.getParentCid().equals(root.getCatId()))
.peek(categoryEntity -> {
// 找到子菜单
categoryEntity.setChildren(getChildless(categoryEntity, all));
})
.sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
.collect(Collectors.toList());
}
另一个
public List<CategoryEntity> listWithLambda() {
List<CategoryEntity> categorys = baseMapper.selectList(Wrappers.<CategoryEntity>lambdaQuery().orderByDesc(CategoryEntity::getCatId))
List<CategoryEntity> entities = new ArrayList<>(categorys);
Map<Long, List<CategoryEntity>> longListNavigableMap = entities.stream().collect(Collectors.groupingBy(CategoryEntity::getParentCid));
List<CategoryEntity> res = entities.stream().peek(entity -> {
if (longListNavigableMap.containsKey(entity.getCatId())) {
entity.setChildren(longListNavigableMap.get(entity.getCatId()));
}
}).filter(entity -> entity.getCatLevel() == 1).sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort()))).collect(Collectors.toList());
return res;
}
方式四:基于Hutool进行构建
导入hutool的依赖,请参考hutool官网
实体类
@Data
@TableName("pms_category")
@AllArgsConstructor
public class CategoryEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 分类id
*/
@TableId
private Long catId;
/**
* 分类名称
*/
private String name;
/**
* 父分类id
*/
private Long parentCid;
/**
* 层级
*/
private Integer catLevel;
/**
* 是否显示[0-不显示,1显示]
*/
@TableLogic(value = "1",delval = "0")
private Integer showStatus;
/**
* 排序
*/
private Integer sort;
/**
* 图标地址
*/
private String icon;
/**
* 计量单位
*/
private String productUnit;
/**
* 商品数量
*/
private Integer productCount;
/**
* 所有子分类
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@TableField(exist = false)
private List<CategoryEntity> children;
}
service
public class TreeUtils{
public List<Tree<Long>> listWithTree() {
ArrayList<CategoryEntity> dataList = Lists.newArrayList();
dataList.add(new CategoryEntity(1L,"电子产品",0L,1,1,0,"/images/electronics.png","件",50,null));
dataList.add(new CategoryEntity(2L,"手机通讯",1L,2,1,0,"/images/electronics.png","件",150,null));
dataList.add(new CategoryEntity(3L,"家用电器",1L,2,1,0,"/images/electronics.png","件",250,null));
List<CategoryEntity> entities = dataList;
if (!CollectionUtil.isEmpty(entities)) {
List<TreeNode<Long>> list = entities.
stream().
map(CategoryServiceImpl::getLongTreeNode).
collect(Collectors.toList());
return TreeUtil.build(list, 0L);
}
return Collections.emptyList();
}
private static TreeNode<Long> getLongTreeNode(CategoryEntity item) {
TreeNode<Long> treeNode = new TreeNode<>();
treeNode.setId(item.getCatId());
treeNode.setParentId(item.getParentCid());
treeNode.setName(item.getName());
treeNode.setWeight(item.getSort());
Map<String, Object> extra = new HashMap<>();
extra.put("showStatus", item.getShowStatus());
extra.put("catLevel", item.getCatLevel());
extra.put("icon", item.getIcon());
extra.put("productUnit", item.getProductUnit());
extra.put("productCount", item.getProductCount());
treeNode.setExtra(extra);
return treeNode;
}
}
测试
public static void main(String[] args) {
List<Tree<Long>> trees = listWithTree1();
System.out.println(JSONUtil.toJsonPrettyStr(trees));
}
方式五
基于mybatisplus的@TableName里面的resultMap属性,当发生查询时,会根据配置的xml查询SQL进行查询
mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xw.mapper.FuncMapper">
<resultMap id="thCloudFuncMap" type="com.xw.entity.Func">
<id column="id" property="id"/>
<result column="creator" property="creator"/>
<result column="creator_name" property="creatorName"/>
<result column="updater" property="updater"/>
<result column="updater_name" property="updaterName"/>
<result column="code" property="code"/>
<result column="name" property="name"/>
<result column="icon" property="icon"/>
<result column="note" property="note"/>
<result column="parent_id" property="parentId"/>
<result column="sort" property="sort"/>
<result column="component_name" property="componentName"/>
<result column="type" property="type"/>
<collection column="id" property="children" select="findByParentId" ofType="com.telehot.tpf.dev.rolemenu.entity.ThCloudFunc">
</collection>
</resultMap>
<select id="findByParentId" resultMap="funcMap">
SELECT * FROM func WHERE parent_id = #{parentId}
</select>
<select id="findAll" resultMap="funcMap">
SELECT * FROM func where is_disabled = 0
</select>
</mapper>
实体类
@TableName(value = "func", resultMap = "funcMap")
public class Func extends Entity {
/**
* 编码
*/
private String code;
/**
* 菜单名称
*/
private String name;
/**
* 图标
*/
private String icon;
/**
* 图标
*/
private String selectIcon;
/**
* 说明
*/
private String note;
/**
* 父类ID
*/
private Long parentId;
/**
* 排序
*/
private Integer sort;
/**
* 类型
*/
private Integer type;
/**
* 路径
*/
private String path;
/**
* 应用id
*/
private String appId;
/***
* 组件名
*/
private String componentName;
/**
* 层级
*/
private Integer tier;
@TableField(exist = false)
private List<Func> children;
}
最后,来一个饭后甜点:java实现 tree结构模糊搜索功能
https://blog.youkuaiyun.com/xiaoshitou_s/article/details/127563692