对递归的一点理解
在项目中经常遇到对于部门这种需要设计父id和子id的程序,或者文件夹的处理。对于这一类问题最好的处理方法还应当是递归处理,在这里先回忆一下递归的方面的一些知识:
递归调用:
- 在一个方法内部对自身的调用就是递归;
- 递归一定要向已知方向递归,即某时刻返回值是已知的,不然变成了无穷递归
递归程序的内部如图所示:
在实际的运用中,可以参考博客:https://blog.csdn.net/weixin_44440642/article/details/106331220。博客作者:不知所终,不知所起。
在本篇博客中仅做学习和记录所用。
在数据库中怎么存储呢这种数据?
id | parentID | name |
1 | 0 | 手机 |
2 | 1 | 智能手机 |
3 | 1 | 非智能手机 |
4 | 2 | 国产智能手机 |
5 | 2 | 非国产智能手机 |
6 | 4 | 华为 |
7 | 4 | 小米 |
8 | 5 | 苹果 |
9 | 5 | 三星 |
我们期望的传递的值:
[ { "id": "1", "parentid": "0", "name": "手机", "children": [ { "id": "2", "parentid": "1", "name": "智能手机", "children": [ { "id": "4", "parentid": "2", "name": "国产智能手机", "children": [ { "id": "6", "parentid": "4", "name": "华为", "children": [] }, { "id": "7", "parentid": "4", "name": "小米", "children": [] } ] }, { "id": "5", "parentid": "2", "name": "非国产智能手机", "children": [ { "id": "8", "parentid": "5", "name": "苹果", "children": [] }, { "id": "9", "parentid": "5", "name": "三星", "children": [] } ] } ] }, { "id": "3", "parentid": "1", "name": "非智能手机", "children": [] } ] } ]
实现:
1定义entity类
//数据库内容 @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @ApiModel(value="shouji", description="") public class Shouji implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) private String id; @TableField("pname") private String pname; @TableField("parentid") private String parentid; }
//扩展类 @Data @ToString public class Shouji Node extends Shouji { List<Shouji > children; }
2.定义mapper
<!--public TeachplanNode selectList(String courseId);--> <select id="selectList" resultType="com.lianxizhifu.springboot.entity.ShoujiNode"> select * from Shouji </select>
List<ShoujiNode> selectList();
3.定义service
List<ShoujiNode> selectList();
@Override public List<ShoujiNode> selectList(String id) { //定义得到的结果封装 List<ShoujiNode> shoujiNodes = shoujiMapper.selectList(); //递归整理父ID和子ID关系 List<ShoujiNode> shoujiNodes1 = this.recursionBuildingGroup(shoujiNodes , id); return shoujiNodes1 ; }
4.具体实现
4.1 方法一使用java代码递归
//递归迭代树型结构 private List<ShoujiNode> recursionBuildingGroup (List<ShoujiNode> ShoujiNodes, String parentId) { //定义接受树型图节点列表 List<ShoujiNode> sonList = new ArrayList<>(); //迭代数据得到所有节点 for (TeachplanNode res : shoujiNodes) { //判断此节点的父ID是否等于要得到的节点 if (res.getParentid().equals(parentId)) { //递归调用当前的ID是否存在子节点 List<ShoujiNode> list = recursionBuildingGroup (shoujiNodes, res.getId()); //得到对应的子节点的集合 res.setChildren(list); sonList.add(res); } } return sonList; }
4.2方法二使用SQL递归
<resultMap id="teachplanMap" type="com.lianxizhifu.springboot.entity.ShoujiNode"> <id column="one_id" property="id"></id> <result column="one_pname" property="pname"></result> <result column="one_parentid" property="parentid"></result> <collection property="children" ofType="com.lianxizhifu.springboot.entity.ShoujiNode"> <id column="tow_id" property="id"></id> <result column="tow_pname" property="pname"></result> <result column="tow_parentid" property="parentid"></result> <collection property="children" ofType="com.lianxizhifu.springboot.entity.ShoujiNode"> <id column="thret_id" property="id"></id> <result column="thret_pname" property="pname"></result> <result column="thret_parentid" property="parentid"></result> </collection> </collection> </resultMap> <!--public TeachplanNode selectList(String courseId);--> <select id="selectList" parameterType="java.lang.String" resultMap="teachplanMap"> SELECT a.id one_id, a.pname one_pname, a.parentid one_parentid b.id tow_id, b.pname tow_pname, b.parentid tow_parentid c.id thret_id, c.pname thret_pname, c.parentid thret_parentid FROM teachplan a LEFT JOIN shosuji b ON b.parentid = a.id LEFT JOIN shosuji c ON c.parentid = b.id WHERE a.parentid = #{id} ORDER BY a.orderby, b.orderby </select>
5.定义controller
@GetMapping("/selectList/{id}") public List<ShoujiNode> selectList(@PathVariable("id") String id) { List<ShoujiNode> shoujis= shoujiService.selectList(id); return shoujis; }
6.结果
[ { "id": "1", "parentid": "0", "name": "手机", "children": [ { "id": "2", "parentid": "1", "name": "智能手机", "children": [ { "id": "4", "parentid": "2", "name": "国产智能手机", "children": [ { "id": "6", "parentid": "4", "name": "华为", "children": [] }, { "id": "7", "parentid": "4", "name": "小米", "children": [] } ] }, { "id": "5", "parentid": "2", "name": "非国产智能手机", "children": [ { "id": "8", "parentid": "5", "name": "苹果", "children": [] }, { "id": "9", "parentid": "5", "name": "三星", "children": [] } ] } ] }, { "id": "3", "parentid": "1", "name": "非智能手机", "children": [] } ] } ]