堆栈替换递归实现多层树形结构
非递归多层树形结构
开发过程中经常会遇到返回一些多层树形结构的需求,而且该属性结构层级不确定,没办法确定用循环次数。此时最方便的方法是使用递归来解决,简单快捷,但是该方式在层级特别深的情况就有问题,可能会导致栈溢出,所以需要使用非递归的方式。
数据准备
// 样例数据,为了图方便使用 guava 包的数据结构
List
递归
@Test
public void testRecuruly() {
List> list = recursively("0");
System.out.println(JSON.toJSONString(list));
}
// 使用递归
List> recursively(String pid) {
List> list = findData(pid);
if(list != null && list.size() > 0) {
for(Map m : list) {
List> list2 = recursively(m.get("id").toString());
m.put("children", list2);
}
}
return list;
}
非递归
递归方式逻辑上很简单,使用非递归的时候主要是参照递归的思路,递归使用jvm栈空间,我们可以创建自己的栈数据结构,在需要入栈的时候代码入栈,来达到递归的效果。java.util.Stack
提供了栈的实现。我们直接用就好了。
// 使用非递归 OK
@Test
public void testStack () {
List> list = findData("0");
// 创建栈
Stack>> stack = new Stack>>();
stack.push(list); // 入栈
while(!stack.isEmpty()) {
List> popList = stack.pop();
for(Map m : popList) {
List> subList = findData(m.get("id").toString());
if(subList != null && subList.size() > 0) {
m.put("children", subList);
stack.push(subList); // 入栈
}
}
}
System.out.println(JSON.toJSONString(list));
}
结果
发现两种方式的结果一致,说明了递归的优化改造完成了。
[
{
"children": [
{
"children": [
{
"pid": "3",
"id": "5",
"tag": "A1"
},
{
"pid": "3",
"id": "5",
"tag": "A2"
},
{
"pid": "3",
"id": "6",
"tag": "B1"
},
{
"pid": "3",
"id": "6",
"tag": "B2"
}
],
"pid": "1",
"id": "3"
},
{
"children": [
{
"pid": "4",
"id": "7",
"tag": "C1"
},
{
"pid": "4",
"id": "8",
"tag": "D1"
},
{
"pid": "4",
"id": "8",
"tag": "D2"
}
],
"pid": "1",
"id": "4"
}
],
"pid": "0",
"id": "1"
},
{
"children": [
{
"children": [
{
"pid": "9",
"id": "11",
"tag": "E1"
},
{
"pid": "9",
"id": "11",
"tag": "E2"
},
{
"pid": "9",
"id": "12",
"tag": "F1"
},
{
"pid": "9",
"id": "12",
"tag": "F2"
}
],
"pid": "2",
"id": "9"
},
{
"children": [
{
"pid": "10",
"id": "13",
"tag": "G1",
"children": [
{
"pid": "13",
"id": "14",
"tag": "H1"
}
]
}
],
"pid": "2",
"id": "10"
}
],
"pid": "0",
"id": "2"
}
]