递归
概述
递归:指在当前方法内调用自己的这种现象。
递归的分类:
注意事项:
- 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。
- 在递归中虽然有限定条件,但是递归次数不能太多。否则也会发生栈内存溢出。
- 构造方法,禁止递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class Demo01DiGui { public static void main(String[] args) { b(1); }
public Demo01DiGui() { }
private static void b(int i) { System.out.println(i); if(i==5000){ return; } b(++i); }
private static void a() { System.out.println("a方法"); a(); } }
|
递归累加求和
计算1 ~ n的和
分析:num的累和 = num + (num-1)的累和,所以可以把累和的操作定义成一个方法,递归调用。
实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class DiGuiDemo { public static void main(String[] args) { int num = 5; int sum = getSum(num); System.out.println(sum); }
public static int getSum(int num) {
if(num == 1){ return 1; }
return num + getSum(num-1); } }
|
1 2 3 4
| 请输入n的值:40 1~40的和为:820
进程已结束,退出代码0
|
代码执行图解
小贴士:递归一定要有条件限定,保证递归能够停止下来,次数不要太多,否则会发生栈内存溢出。
递归求阶乘
1
| n的阶乘:n! = n * (n-1) *...* 3 * 2 * 1
|
分析:这与累和类似,只不过换成了乘法运算,学员可以自己练习,需要注意阶乘值符合int类型的范围。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class DiGuiDemo { public static void main(String[] args) { int n = 3; int value = getValue(n); System.out.println("阶乘为:"+ value); }
public static int getValue(int n) { if (n == 1) { return 1; }
return n * getValue(n - 1); } }
|
1 2 3 4
| 请输入n的值:5 5的阶乘为:120
进程已结束,退出代码0
|
递归打印多级目录
分析:多级目录的打印,就是当目录的嵌套。遍历之前,无从知道到底有多少级目录,所以我们还是要使用递归实现。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class DiGuiDemo2 { public static void main(String[] args) { File dir = new File("D:\\aaa"); printDir(dir); }
public static void printDir(File dir) { File[] files = dir.listFiles();
for (File file : files) { if (file.isFile()) { System.out.println("文件名:"+ file.getAbsolutePath()); } else { System.out.println("目录:"+file.getAbsolutePath()); printDir(file); } } } }
|
1 2 3 4 5 6 7 8 9 10 11
| 文件名:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\2.txt 目录:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\a 文件名:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\a\2.txt 目录:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\a\b 文件名:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\a\b\2.txt 文件名:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\a\b\test4.java 目录:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\aa 目录:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\aa\bb 文件名:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\aa\test3.java
进程已结束,退出代码0
|
综合案例
文件搜索
搜索D:\aaa
目录中的.java
文件。
分析:
- 目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。
- 遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class DiGuiDemo3 { public static void main(String[] args) { File dir = new File("D:\\aaa"); printDir(dir); }
public static void printDir(File dir) { File[] files = dir.listFiles(); for (File file : files) { if (file.isFile()) { if (file.getName().endsWith(".java")) { System.out.println("文件名:" + file.getAbsolutePath()); } } else { printDir(file); } } } }
|
1 2 3 4
| 文件名:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\a\b\test4.java 文件名:E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\aa\test3.java
进程已结束,退出代码0
|
文件过滤器优化
java.io.FileFilter
是一个接口,是File的过滤器。 该接口的对象可以传递给File类的listFiles(FileFilter)
作为参数, 接口中只有一个方法。
boolean accept(File pathname)
:测试pathname是否应该包含在当前File目录中,符合则返回true。
分析:
- 接口作为参数,需要传递子类对象,重写其中方法。我们选择匿名内部类方式,比较简单。
accept
方法,参数为File,表示当前File下所有的子文件和子目录。保留住则返回true,过滤掉则返回false。保留规则:
- 要么是.java文件。
- 要么是目录,用于继续遍历。
- 通过过滤器的作用,
listFiles(FileFilter)
返回的数组元素中,子文件对象都是符合条件的,可以直接打印。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class DiGuiDemo4 { public static void main(String[] args) { File dir = new File("D:\\aaa"); printDir2(dir); } public static void printDir2(File dir) { File[] files = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.getName().endsWith(".java")||pathname.isDirectory(); } }); for (File file : files) { if (file.isFile()) { System.out.println("文件名:" + file.getAbsolutePath()); } else { printDir2(file); } } } }
|
1 2 3 4
| E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\a\b\test4.java E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\aa\test3.java
进程已结束,退出代码0
|
Lambda优化
分析:FileFilter
是只有一个方法的接口,因此可以用lambda表达式简写。
lambda格式:
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void printDir3(File dir) { File[] files = dir.listFiles(f ->{ return f.getName().endsWith(".java") || f.isDirectory(); }); for (File file : files) { if (file.isFile()) { System.out.println("文件名:" + file.getAbsolutePath()); } else { printDir3(file); } } }
|
1 2 3 4
| E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\a\b\test4.java E:\学习笔记\Java\java编程基础\improve-code\day08-code\test\aa\test3.java
进程已结束,退出代码0
|