目录
一、什么是递归?
二、示例分析
一、什么是递归?
递归调用是一种特殊的嵌套调用,是某个函数调用自己或者是调用其他函数后再次调用自己的,只要函数之间互相调用能产生循环的则一定是递归调用,递归调用一种解决方案,一种是逻辑思想,将一个大工作分为逐渐减小的小工作,比如说一个和尚要搬50块石头,他想,只要先搬走49块,那剩下的一块就能搬完了,然后考虑那49块,只要先搬走48块,那剩下的一块就能搬完了,递归是一种思想,只不过在程序中,就是依靠函数嵌套这个特性来实现了。
递归调用就是在当前的函数中调用当前的函数并传给相应的参数,这是一个动作,这一动作是层层进行的,直到满足一般情况的的时候,才停止递归调用,开始从最后一个递归调用返回。
二、示例分析
案例1:递归删除菜单及其所有子菜单
- 菜单实体类
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;
import java.util.Date;/*** 系统菜单*/
@Data
@TableName(value = "menu")
public class Menu implements Serializable {private static final long serialVersionUID = 1L;/*** 菜单ID*/@TableId(type = IdType.INPUT)private Long menuId;/*** 父级菜单ID*/private Long upMenuId;/*** 菜单编码*/private String menuCode;/*** 菜单名称*/private String menuName;/*** 菜单级别(默认1级)*/private Integer menuLevel;/*** 菜单页面打开方式(1-本页面打开 2 新标签页打开 3-新窗口打开)*/private Integer pageOpenType;/*** 菜单类型(1-菜单 2-权限按钮)*/private Integer menuType;/*** 菜单图标*/private String menuIcon;/*** 菜单URL*/private String menuUrl;/*** 菜单序号*/private Integer menuOrder;/*** 菜单描述*/private String menuDesc;/*** 数据状态(0-删除 1-正常) */private Integer dataFlag;/*** 是否禁用(0-否 1-是)*/private Integer isDisable;/*** 创建人ID*/private Long createId;/*** 创建时间*/private Date createTime;}
- 实现代码
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.test.java.domain.entity.Menu;
import com.test.java.mapper.MenuMapper;
import com.test.java.service.MenuService;
import org.springframework.util.CollectionUtils;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;public class MenuServiceImpl implements MenuService {@Resourceprivate MenuMapper menuMapper;@Overridepublic Integer deleteMenuById(Long menuId) {// 校验当前要删除的菜单是否存在Menu menu = menuMapper.selectById(menuId);if (null == menu) {throw new RuntimeException("菜单已删除");}// 创建list集合,用于封装所有要删除的菜单IDList<Long> menuIdList = new ArrayList<>();// 向menuIdList集合设置删除菜单id(根据id删除菜单)this.queryMenuChildById(menuId, menuIdList);// 把当前菜单id封装到idList里面menuIdList.add(menuId);// 批量删除当前菜单 及其所有子菜单return menuMapper.deleteBatchIds(menuIdList);}// 根据当前菜单id,查询其所有子菜单id,再封装到idList集合private void queryMenuChildById(Long menuId, List<Long> idList) {// 查询菜单里面子菜单idQueryWrapper<Menu> wrapper = new QueryWrapper<>();wrapper.eq("up_menu_id", menuId);List<Menu> childMenuList = menuMapper.selectList(wrapper);if (!CollectionUtils.isEmpty(childMenuList)) {// 把childMenuList里面菜单id值获取出来,封装idList里面,做递归查询childMenuList.forEach(item -> {//封装idList里面idList.add(item.getMenuId());//递归查询this.queryMenuChildById(item.getMenuId(), idList);});}}}
案例2:递归删除目录及其目录中所有文件
- 实现代码
import lombok.extern.slf4j.Slf4j;import java.io.File;/*** 文件相关工具类*/
@Slf4j
public class FileUtils {/*** 删除文件或文件夹** @param path 文件路径* @return 返回true(删除成功), 返回false(删除失败)*/public static boolean deleteFileOrDirectory(String path) {File file = new File(path);// 判断文件是否存在if (file.exists()) {// 判断是否为文件if (file.isFile()) {// 删除文件return deleteFile(path);} else {// 删除文件夹return deleteDirectory(path);}} else {return false;}}/*** 删除文件** @param path 文件路径* @return 返回true(删除成功), 返回false(删除失败)*/public static boolean deleteFile(String path) {boolean result = false;File file = new File(path);if (file.isFile() && file.exists()) {result = file.delete();log.info("删除文件成功:{}", path);return result;} else {log.info("删除文件失败:{}", path);return result;}}/*** 删除文件夹(先删文件再删目录)** @param path 文件夹路径* @return 返回true(删除成功), 返回false(删除失败/文件夹不存在)*/public static boolean deleteDirectory(String path) {if (!path.endsWith(File.separator)) {// 补齐文件分隔符path = path + File.separator;}File directoryFile = new File(path);// 文件不存在、不是一个目录就打印退出返回falseif (!directoryFile.exists() || !directoryFile.isDirectory()) {log.info("文件夹不存在,{}", path);return false;}boolean flag = true;// 获取所有的子文件及子文件夹File[] files = directoryFile.listFiles();if (files != null) {// 循环删除for (File file : files) {// 删除子文件if (file.isFile()) {flag = deleteFile(file.getAbsolutePath());if (!flag) {break;}} else {// 删除子文件夹flag = deleteDirectory(file.getAbsolutePath());if (!flag) {break;}}}}if (!flag) {log.info("删除文件夹失败");return false;}// 最后删除当前文件夹if (directoryFile.delete()) {log.info("删除文件夹成功,{}", path);return true;} else {log.info("删除文件夹失败,{}", path);return false;}}}
以上代码直接粘贴复制即可直接使用。
如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。