递归
概述
递归:指的是当前方法调用自己的一种现象。
递归的分类:
递归分为两类:直接递归和间接递归
直接递归:称为方法自身调用自己的情况
间接递归:可以归结为:方法A调用了方法B,方法B调用了方法C,方法C反过来又调用了方法A。
注意事项:
递归一定要有边界条件(条件限定),保证递归能够停止下来,否则会发生栈内存溢出。
在递归当中虽然有限定条件,但是递归的次数也不能太多,否则也会发生栈内存溢出现象。
构造方法禁止递归。
使用递归实现累加求和
计算1~n之间的和
图解分析:
递归求阶乘
阶乘:所有小于及等于该数的正整数的乘积。
n的阶乘:n! = n * (n-1) * (n-2) * (n-3) * … * 3 * 2 * 1
package com.zhiyou100.recursion.demo01;
/*
练习使用递归计算1~n之间的和
及n的阶乘
*/
public class Demo02Recursion {
public static void main(String[] args) {
long sum = sum(100);
System.out.println(sum);
int product = product(5);
System.out.println(product);
}
/*
定义一个方法:使用递归操作
1 + 2 + 3 + 4 + ... + n
n + (n - 1) + (n - 2) + ... + 1
使用递归必须明确:
1.递归的结束条件:获取到1的时候结束
2.递归的目的:获取下一个被加的数字(n-1)
*/
public static long sum(long n) {
if (n == 1) {
return 1;
}
return n + sum(n - 1);
}
// 累乘
public static int product(int n){
if (n == 1){
return 1;
}
return n * product(n - 1);
}
}
使用递归打印多级目录
代码示例:
public static void main(String[] args) {
// 找到Hello文件的路径
File file = new File("C:\\Users\\admin\\Desktop\\Hello");
//调用getAllFiles()
getAllFiles(file);
}
/*
定义一个方法,参数传递File类型的目录
方法中要对目录进行遍历
*/
public static void getAllFiles(File file) {
// 表明file此时是一个目录
System.out.println(file);
//首先先获取到它直接子目录和直接子文件
File[] files = file.listFiles();
// 遍历files目录
for (File f : files) {
// 判断如果得到的f是一个目录,需要再次遍历
if (f.isDirectory()) {
// 表明f是一个目录,则继续遍历这个目录
//getAllFiles方法就是获取所有的文件,参数传递的刚好是目录。所以直接调用getAllFiles:递归(自己调用自己)
getAllFiles(f);
} else {
// 此时f不是一个目录,肯定是一个文件
System.out.println(f);
}
}
}
综合案例
文件搜索
搜索:C:\Users\admin\Desktop\Hello目录中的所有的.txt文件
分析:
1.目录搜索,无法判断有多少级目录,所以使用递归,遍历所有的目录
2.遍历目录的时候,获取的是所有的子文件,通过文件的名称来进行诊断,判断是否符合给定的条件.txt
代码实现:
public static void main(String[] args) {
//构建一个File对象得到C:\Users\admin\Desktop\Hello路径
File file = new File("C:\\Users\\admin\\Desktop\\Hello");
getAllTxt(file);
}
/*
定义一个方法,遍历所有的.txt文件
方法中依然需要传参数目录
*/
public static void getAllTxt(File dir) {
//System.out.println(dir);
File[] files = dir.listFiles();
//遍历files
for (File f : files) {
// 判断f是否是一个目录
if (f.isDirectory()) {
getAllTxt(f);
} else {
// 先获取文件的名称
/* String name = f.getName();
//String path = f.getPath();
// 大写字符串转换成小写
name = name.toLowerCase();
// 再次判断名称是否以.txt结尾
if (name.endsWith(".txt")) {
System.out.println(f);
}*/
// 链式编程
if (f.getName().toLowerCase().endsWith(".txt")) {
System.out.println(f);
}
}
}
}
文件过滤器优化
java.io.FileFilter
是一个接口,是File的过滤器,该接口的对象可以传递给File类的listFiles(FileFilter)作为参数,接口当中只有一个方法:
boolean accept(File pathname)
:测试pathname是否应该包含在当前的File目录中,如果符合返回true。
public static void main(String[] args) {
//构建一个File对象得到C:\Users\admin\Desktop\Hello路径
File file = new File("C:\\Users\\admin\\Desktop\\Hello");
getAllTxt(file);
}
/*
定义一个方法,遍历所有的.txt文件
方法中依然需要传参数目录
*/
public static void getAllTxt(File dir) {
//System.out.println(dir);
//File[] files = dir.listFiles();
File[] files = dir.listFiles(new FileFilterImpl());
//遍历files
for (File f : files) {
// 判断f是否是一个目录
if (f.isDirectory()) {
getAllTxt(f);
} else {
// 先获取文件的名称
System.out.println(f);
}
}
}
// 实现类中的代码
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return true;
}
return pathname.getName()
.toLowerCase()
.endsWith(".txt");
}
Lambda优化
示例代码:
//FilenameFilter接口
File[] files = dir.listFiles((d,name) -> new File(d,name).isDirectory() || name.toLowerCase().endsWith(".txt"));
//FileFilter接口
File[] files = dir.listFiles(pathname ->pathname.getName().toLowerCase().endsWith(".txt") || pathname.isDirectory());