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