使用Stream的groupBy实现多级菜单查询
1 概述
查询多级菜单的结果,例如 优惠券树,后台系统的侧边栏的权限树等。
2 实现
使用stream的groupingBy方法,可以将集合根据方法内部的参数进行分组,相同参数的放在一起,就拿到了一个Map(key为菜单id,value为当前菜单下子菜单的集合),然后遍历Map,在Map内部进行对子菜单的重新赋值。
代码如下:
@RequestMapping("tree")
public ResponseWrapper tree2(){
//查询所有的菜单集合
List<Tree> allList = treeMapper.selectAll();
//所有父级菜单的id
List<Integer> parentTreeList = allList.stream().filter(e -> e.getModelLevel() == 1).map(Tree::getModeId).collect(Collectors.toList());
//对所有非父级菜单根据其父菜单id进行分组
Map<Integer, List<Tree>> suTreeMap = allList.stream().filter(e -> e.getModelLevel() != 1).collect(Collectors.groupingBy(Tree::getParentId));
List<Tree> result = new ArrayList<>();
//遍历分组后的map
for (Map.Entry<Integer, List<Tree>> subTreeMap : suTreeMap.entrySet()) {
//获取指定菜单id的菜单对象
Tree treeById = getTreeById(subTreeMap.getKey(), allList);
//对当前菜单的子菜单进行赋值
treeById.setChildrenTree(subTreeMap.getValue());
result.add(treeById);
}
//去除非父菜单的结果
result.removeIf(e->!parentTreeList.contains(e.getModeId()));
ResponseWrapper responseWrapper = ResponseWrapper.newSuccess();
responseWrapper.addData(result);
return responseWrapper;
}
/**
* 根据菜单id获取菜单对象
* @param treeId 菜单id
* @param all 所有菜单对象
*/
public Tree getTreeById(Integer treeId, List<Tree> all){
return all.stream().filter(e -> e.getModeId().equals(treeId)).collect(Collectors.toList()).get(0);
}
Tree实体:
public class Tree {
private Integer id;
private Integer parentId;//父级菜单id
private Integer modeId;//菜单id
private String modelName;
private String modelUrl;
private String appName;
private Byte modelLevel;//菜单等级 1:一级菜单 2:二级菜单....
private List<Tree> childrenTree;//子菜单集合
//get/set方法略去
}