前言
我们在日常开发时经常会遇到需要给前端返回树结构数据,并且有的数据是无限极的,这个时候我们就需要递归算法。
一、递归算法是什么
递归算法(英语:recursion algorithm)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。递归式方法可以被用于解决很多的计算机科学问题,因此它是计算机科学中十分重要的一个概念。绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。计算理论可以证明递归的作用可以完全取代循环,因此在很多函数编程语言(如Scheme)中习惯用递归来实现循环。
就是方法自己调用自己。
二、示例说明
1.场景说明
在实际开发中经常遇到这些场景的时候:
有的时候不需要后端处理,前端就可以处理,但是有的时候不要要后端处理,这个时候就需要递归数据组装了。
2.java示例
比如我们需要给前端返回这样无限极的数据 superiorId:是标记的上级ID children:是下级集合。
注:我看到有的同事一直在递归循环中查询数据库得数据,这样的做法是不可取的,数据少了还不明显,数据多了会严重拖慢速度,也会带来巨大的开销。应该直接取出全部数据,然后用代码拼接数据。
代码如下:
1.先建一个实体类(用于演示):
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.util.List;
@Getter
@Setter
@Accessors(chain = true)
public class TerrTest {
private String id;
private String name;
private Integer age;
/**
* 上级id
*/
private String superiorId;
private String address;
/**
* 下级数据
*/
private List<TerrTest> children;
public TerrTest(String id, String name, Integer age, String superiorId, String address) {
this.id = id;
this.name = name;
this.age = age;
this.superiorId = superiorId;
this.address = address;
}
}
2.举例说明:
比如有这样一个list数据要转换成树结构:
import com.alibaba.fastjson.JSON;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 树结构
*
* @author Administrator
*/
public class ListTurnTreeUtil {
/**
* 递归组装树结构
*
* @param superiorId 父级id
* @param list list数据
* @return 组装完成的数据
*/
public static List<TerrTest> queryTerr(String superiorId, List<TerrTest> list){
List<TerrTest> children = new ArrayList<>();
for(TerrTest t : list){
if(superiorId.equals(t.getSuperiorId())){
children.add(t);
t.setChildren(queryTerr(t.getId(), list));
}
}
return children;
}
public static void main(String[] args) {
List<TerrTest> list = new ArrayList<>();
Collections.addAll(list,
new TerrTest("1", "第一级1", 10, "0", "第一级1地址"),
new TerrTest("12", "第二级1", 20, "1", "第二级1地址"),
new TerrTest("13", "第二级2", 21, "1", "第二级2地址"),
new TerrTest("121", "第三级1", 30, "12", "第三级1地址"),
new TerrTest("2", "第一级2", 10, "0", "第一级2地址"));
System.out.println(JSON.toJSON(queryTerr("0", list)));
}
}
查看打印结构:
这样不是很直观,格式化一下在看:
可以看的已经转换完成了。
树结构转换通用方法
上面方法虽然转换成功了,但是只能用于这一个实体类,换一个实体类还要在写一遍,所以我写了个通用的方法,感兴趣的大家可以使用下。
代码如下:
只需传入 id的名称、父级id的名称、下级集合的名称 就可以轻松转换各种List实体类数据了。
import com.alibaba.fastjson.JSON;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 树结构
*
* @author Administrator
*/
public class ListTurnTreeUtil {
/**
* 递归组装树结构
*
* @param superiorId 父级id
* @param list list数据
* @param currentLevelIdName id的名称
* @param superiorIdName 父级id的名称
* @param childrenName 下级集合的名称
* @return 组装完成的数据
* @throws IllegalAccessException
* @throws NoSuchFieldException
*/
public static List<?> queryTerr(Object superiorId, List<?> list,
String currentLevelIdName, String superiorIdName,
String childrenName) throws IllegalAccessException, NoSuchFieldException {
List<Object> children = new ArrayList<>();
for(Object t : list){
Field fieldSuperiorIdName = t.getClass().getDeclaredField(superiorIdName);
fieldSuperiorIdName.setAccessible(true);
Object tSuperior = fieldSuperiorIdName.get(t);
fieldSuperiorIdName.setAccessible(false);
if(superiorId.equals(tSuperior)){
children.add(t);
Field fieldCurrentLevelIdName = t.getClass().getDeclaredField(currentLevelIdName);
fieldCurrentLevelIdName.setAccessible(true);
Object tCuLeIdName = fieldCurrentLevelIdName.get(t);
fieldCurrentLevelIdName.setAccessible(false);
Field fieldEntity = t.getClass().getDeclaredField(childrenName);
fieldEntity.setAccessible(true);
fieldEntity.set(t, queryTerr(tCuLeIdName, list, currentLevelIdName, superiorIdName, childrenName));
fieldEntity.setAccessible(false);
}
}
return children;
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
List<TerrTest> list = new ArrayList<>();
Collections.addAll(list,
new TerrTest("1", "第一级1", 10, "0", "第一级1地址"),
new TerrTest("12", "第二级1", 20, "1", "第二级1地址"),
new TerrTest("13", "第二级2", 21, "1", "第二级2地址"),
new TerrTest("121", "第三级1", 30, "12", "第三级1地址"),
new TerrTest("2", "第一级2", 10, "0", "第一级2地址"));
System.out.println(JSON.toJSON(queryTerr("0", list,
"id", "superiorId", "children")));
}
}