递归
递归
概述
递归:指的是当前方法调用自己是一种现象。
-
递归的分类:
-
递归分为两类:之间递归和间接递归
-
直接递归:称为方法自身调用自己的情况
-
间接递归:可以归结为:方法A调用了方法B,方法B调用了方法C,方法C反过来又调用了方法A。
- 注意事项:
-
递归一定要有边界条件(条件限定) ,保证递归能够停止下来,否则会发生栈内存溢出。
-
在递归当中虽然有限定条件,但是递归的次数也不能太多,否则也会发生栈内存溢出现象。
-
构造方法禁止递归。
示例代码:
public class Demo01Recursion{
public static void main(String[] args){
sum(1);
int i = sum02(20000);
System.out.println(i);
}
}
/*
定义一个方法,求和的方法
对于递归虽然有边界条件,但是递归的次数不能太多,否则依然会抛出栈内存溢出错误。
*/
public static int sum02(int n){
Syatem.out.println(n);
if(n==1){
return 1;
}
return n+sum02(n-1);
}
/* 1+ 2 + 3 + 4 + 5 + ..... + n
n+ n-1 + n-2 + n-3 + .... + 1
定义求和的方法
Exception in thread "main" java.lang.StackOverflowError
递归一定要有边界条件,保证递归能够停止下来。
*/
public static int sum(int n){
System.out.println("当前n的值为:"+n);
return n+sum(n-1);
}
}
使用递归实现累加和
计算1~n的和
分析:1+2+3+4+5+6+7+...+n--->n+(n-1)+(n-2)+(n-3)+(n-4)+...+(n-n-1);
public class Demo02Recursion {
public static void main(String[] args) {
int sum = sum(10);
System.out.println(sum);
}
public static int sum(int n){
//边界条件
if (n==1){
return 1;
}
//获取下一个被加的数字
return n+sum(n-1);
}
}
递归求阶乘
- 阶乘:所有小于及等于该数的正整数的乘积。
n的阶乘: n!=n(n-1) (n-2)* (n-3)....321
代码示例:
public class Demo02Recursion {
public static void main(String[] args) {
int sum = sum(10);
System.out.println(sum);
}
public static int sum(int n){
//边界条件
if (n==1){
return 1;
}
//获取下一个被加的数字
return n*sum(n-1);
}
}
使用递归打印多级目录
public class Demo04Recursion {
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);
/* File[] files1 = f.listFiles();
for (File file1 : files1) {
}*/
} else {
// 此时f不是一个目录,肯定是一个文件
System.out.println(f);
}
}
}
}
综合案例
文件搜索
搜索: C:Users\admin\DesktoplHello目录中的所有的.txt文件
分析:
-
目录搜索,无法判断有多少级目录,所以使用递归,遍历所有的目录
-
遍历目录的时候,获取的是所有的子文件
public class FileFilterImpl implements FileFilter {
/*
过滤的规则:
在accept方法中,判断File类对象是否以.txt结尾
是就返回true
不是就返回false
如果此File对象是一个文件夹,则返回true,继续遍历这个文件夹
*/
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return true;
}
return pathname.getName()
.toLowerCase()
.endsWith(".txt");
}
}
public class Demo07Recursion {
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) {
//匿名内部类的写法
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return true;
}
return pathname.getName().toLowerCase().endsWith(".txt");
}
});
// 使用FilenameFilter
File[] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
if (pathname.isDirectory()) {
return true;
}
return pathname.getName().toLowerCase().endsWith(".txt");
}
});
File[] files = dir.listFiles((File d, String name) -> {
return new File(d,name).isDirectory() || name.toLowerCase().endsWith(".txt");
});
File[] files = dir.listFiles((d,name) -> new File(d,name).isDirectory() || name.toLowerCase().endsWith(".txt"));
// 使用Lambda表达式优化
File[] files = dir.listFiles((File pathname) -> {
return pathname.getName().toLowerCase().endsWith(".txt") || pathname.isDirectory();
});
// 可以再次优化下代码
File[] files = dir.listFiles(pathname ->pathname.getName().toLowerCase().endsWith(".txt") || pathname.isDirectory());
/*
C:\Users\admin\Desktop\Hello\aa\123.txt
C:\Users\admin\Desktop\Hello\bb\bb.txt
C:\Users\admin\Desktop\Hello\cc\cc.txt
C:\Users\admin\Desktop\Hello\hello (2).TXT
C:\Users\admin\Desktop\Hello\hello.txt
*/
//遍历files
for (File f : files) {
// 判断f是否是一个目录
if (f.isDirectory()) {
getAllTxt(f);
} else {
// 先获取文件的名称
System.out.println(f);
}
}
}
}