Java基础(二十二) 递归
递归
概述
- 递归:指的是当前方法调用自己的现象。
- 递归的分类:
- 递归分为两类:直接递归和间接递归
- 直接递归:成为方法自身调用自己的情况
- 间接递归:可以归结为:方法A调用了方法B,方法B调用了方法C,方法C返回来又调用了方法A。
注意事项:
-
-
- 递归一定要有边界条件(条件限定),保证递归能够停止下来,否则会发生栈内存溢出。
- 在递归当中虽然有限定条件,但是递归的次数也不能太多,否则也会发生栈内存异常现象。
- 构造方法禁止递归。
-
使用递归实现累计求和
计算1~n之间的和
分析:1+2+3+...+n---->n + (n-1) + (n - 2) + ...+1的累加和,递归调用。
代码示例:
1 public static void main(String[] args) {
2 int sum = sum(10);
3 System.out.println(sum);
4 }
/*
定义一个方法,使用递归操作
1 + 2 + 3+ 4 +...+n
n+(n-1)+(n-2)+(n-3)+…+1
已知:
最大值:n
最小值:1
使用递归必须明确:
1.递归的结束条件
2.递归的目的:获取下一个被加的数字(n-1)
*/
public static int sum(int n){
if(n == 1){
return 1;
}
//获取下一个被加的数字
return n + sum(n-1);
//return n == 1 ? 1 : sum(n-1) + n; 使用三目运算符更方便
}
备注:使用递归当中,main方法调用sum方法,sum方法会一直调用sum方法,导致在内存当中出现了很多个sum方法(频繁地创建方法、调用方法、销毁方法)效率非常低下,最好的方式就是for循环。
递归求阶乘
阶乘:所有小于及等于该数的正整数的乘积。
n的阶乘:n! = n * (n-1) * (n-2) * (n-3) * ... * 3 * 2 * 1
代码示例:
1 public static int producr(int n){
2
3 if( n == 1){
4 return 1;
5 }
6 return producr(n-1) * n;
7 }
使用递归打印多级目录
代码示例:
1 public static void main(String[] args) { 2 // 找到Hello文件的路径 3 File file = new File("C:\\Users\\admin\\Desktop\\Hello"); 4 //调用getAllFiles() 5 getAllFiles(file); 6 } 7 8 /* 9 定义一个方法,参数传递File类型的目录 10 方法中要对目录进行遍历 11 */ 12 public static void getAllFiles(File file) { 13 // 表明file此时是一个目录 14 System.out.println(file); 15 //首先先获取到它直接子目录和直接子文件 16 File[] files = file.listFiles(); 17 // 遍历files目录 18 if (files != null) { 19 for (File f : files) { 20 //判断如果得到的f是一个目录的,需要再次遍历 21 if (f.isDirectory()) { 22 //表明f是一个目录,则继续遍历这个目录 23 //getAllFiles方法就是获取所有的文件,参数传递的刚好是目录,所以直接调用 24 //getAllFiles目录 25 System.out.println(f); 26 getAllFiles(f); 27 } else { 28 System.out.println(f); 29 } 30 } 31 } 32 }
综合案例
文件搜索
搜索:C:\Users\admin\Desktop\Hello目录中的所有的.txt文件
分析:
1.目录搜索,无法判断有多少级目录,所以使用递归,遍历所有的目录
2.遍历目录的时候,获取的是所有的子文件,通过文件的名称来进行诊断,判断是否符合给定的条件.txt
代码实现:
1 public static void main(String[] args) {
2 //构建一个File对象得到C:\Users\admin\Desktop\Hello路径
3 File file = new File("C:\\Users\\admin\\Desktop\\Hello");
4 getAllTxt(file);
5
6 }
7 /*
8 定义一个方法,遍历所有的.txt文件
9 方法中依然需要传递参数目录
10 */
11 public static void getAllTxt(File dir){
12 File[] files = dir.listFiles();
13 //遍历files
14 if(files != null){
15 for (File f : files) {
16 //判断f是否是一个目录
17 if(f.isDirectory()){
18 getAllTxt(f);
19 }else {
20 //先获取文件的名称
21 //再次判断名称是否以.txt结尾
22 //链式编程
23 if(f.getName().toLowerCase().endsWith(".txt")){
24 System.out.println(f);
25 }
26 }
27 }
28 }
29 }
文件过滤器优化
java.io.FileFilter是一个接口,是File的过滤器,该接口的对象可以传递给File类的ListFiles(FileFilter)作为参数,接口当中只有一个方法:
boolean accept(File pathname):测试pathname是否应该包含在当前的File目录中,如果符合返回true
示例代码:
1 public static void main(String[] args) {
2 //构建一个File对象得到C:\Users\admin\Desktop\Hello路径
3 File file = new File("C:\\Users\\admin\\Desktop\\Hello");
4 getAllTxt(file);
5 }
6 /*
7 定义一个方法,遍历所有的.txt文件
8 方法中依然需要传参数目录
9 */
10 public static void getAllTxt(File dir) {
11 //System.out.println(dir);
12 //File[] files = dir.listFiles();
13 File[] files = dir.listFiles(new FileFilterImpl());
14 //遍历files
15 for (File f : files) {
16 // 判断f是否是一个目录
17 if (f.isDirectory()) {
18 getAllTxt(f);
19 } else {
20 // 先获取文件的名称
21 System.out.println(f);
22 }
23 }
24 }
25 // 实现类中的代码
26 @Override
27 public boolean accept(File pathname) {
28 if (pathname.isDirectory()) {
29 return true;
30 }
31 return pathname.getName()
32 .toLowerCase()
33 .endsWith(".txt");
34 }
Lambda优化
示例代码:
1 //FilenameFilter接口
2 File[] files = dir.listFiles((d,name) -> new File(d,name).isDirectory() || name.toLowerCase().endsWith(".txt"));
3 //FileFilter接口
4 File[] files = dir.listFiles(pathname ->pathname.getName().toLowerCase().endsWith(".txt") || pathname.isDirectory());