文章目录
- 菜单树递归(树根往子节点递归)
- 需求: 取所有level小于2的节点 ( 返回结果为普通list格式)
- 为list格式的数据设置children(非递归)
- 需求: 数据库查出来的原始list 如果有children就设置
- 使用循环代替向下递归
- 需求:使用循环的方式 代替菜单树的递归
递归会造成压栈 栈帧变多 容易Stack Overflow,所以递归一般用于有限且数量可控范围内
个人是很讨厌递归的,一般要用到递归的实际场景,代码就是又臭又长了,但这也是最简单粗暴的算法了,所以记录个工作中遇到的递归案例,平常也需要加强练习,遇到才不会不知所措。
菜单树递归(树根往子节点递归)
需求: 取所有level小于2的节点 ( 返回结果为普通list格式)
Tree结构
private Long id;private Long fid;private Integer level;private List<Tree> children;
allTreeList数据:

代码实现:
// SysMenuDTO 继承TreeList<SysMenuDTO> res= new ArrayList<>();res= handleChild(allTreeList, res);
handleChild 方法:
private List<SysMenuDTO> handleChild(List<SysMenuDTO> treeList, List<SysMenuDTO> resList) {for (SysMenuDTO each : treeList) {if (each.getLevel() < 2) {resList.add(each);}if (null != each.getChildren()) {List<Tree> children = each.getChildren();// 转型List<SysMenuDTO> treeChild = new ArrayList<>();for (Tree child : children) {treeChild.add((SysMenuDTO) child);}handleChild(treeChild, resList);}}return resList;}
为list格式的数据设置children(非递归)
需求: 数据库查出来的原始list 如果有children就设置
Tree结构同上
list数据: 可以看到此时的数据是平铺的 children为null

代码实现:
// allTreeList 结构同上
List<SysMenuDTO> allTreeList = Tree.assembleTree(allList);
public static <T extends Tree> List<T> assembleTree (List<T> vos) {/*如果节点数为0或1,则不需要组装*/if ( vos == null ) {return vos;}List<T> retList = new ArrayList<>();Map<Long, T> map = new HashMap<>();for (T item : vos) {int level = getLevel(item.getCode());item.setLevel(level);map.put(item.getId(), item);if (item.getFid() == null || item.getFid() == 0 ) {retList.add(item);continue;}T fNode = map.get(item.getFid());if (null != fNode) {List<Tree> subs = fNode.getChildren();if (null == subs) {subs = new ArrayList<>();fNode.setChildren(subs);}subs.add(item);} else {log.error("Failed to get father node: {}", item);}}return retList;}
使用循环代替向下递归
需求:使用循环的方式 代替菜单树的递归
这个时候我们要借助第三方容器,通常使用栈或队列。
代码实现:
// 所有菜单树List<SysMenuDTO> allTreeList = xxx;// 一二级菜单树 level从0开始List<SysMenuDTO> res = new ArrayList<>();Queue<SysMenuDTO> queue = new LinkedBlockingDeque() ;for (SysMenuDTO each : allTreeList) {// 将每个节点放入队列中queue.offer(each);}while (!queue.isEmpty()) {// 出队列SysMenuDTO each = queue.poll();if (Optional.ofNullable(each.getLevel()).orElse(0) < 2) {res.add(each);}if (null != each.getChildren()) {List<Tree> children = each.getChildren();for (Tree eachElement : children) {// 子节点不为空 将子节点的每个对象入队列queue.offer((SysMenuDTO) eachElement);}}}















