什么是递归?有哪些应用?
递归:把大问题拆成很多小问题,然后再把小问题拆成更多的小问题,当我们把更多小问题解决了,小问题也解决了,随着小问题的解决,大问题也随之解决了
在方法本身不断的调用方法自己
递归注意事项:
递归一定要有出口,内存溢出
递归次数不宜过多,内存溢出
递归必须要有规则
一些递归案例
案例1:从键盘接收一个文件夹路径,统计该文件夹大小
package com.digui.test;
import java.io.File;
import java.util.Scanner;
public class Test01 {
/**
* 需求:从键盘接收一个文件夹路径,统计该文件夹大小
* 如何从键盘接收文件夹路径
* 1.创建键盘录入对象
* 2.定义一个无限循环
* 3.将键盘录入的结果存储并封装成File对象
* 4.对File对象判断
* 5.将文件夹路径对象返回
*
* 如何统计文件夹大小呢?如果之间统计文件夹大小,结果为0.
* 1.定义求和变量
* 2.获取文件夹下的所有文件和文件夹,listFiles()方法
* 3.遍历数组
* 4.判断是文件就计算大小并累加
* 4.判读是文件夹就递归调用
*
* 分析:
* 考虑递归需要一层一层的分析,并且有共性,可以嵌套
*/
public static void main(String[] args) {
File file = getDir();
long num = getFileLength(file);
System.out.println(file+"文件大小为"+num);
}
/*
* 如何统计文件夹大小
* 返回值类型:long
* 参数列表:File file
*/
public static long getFileLength(File file) {
long num = 0;
File[] dir = file.listFiles();
for (File getDir : dir) {
if(getDir.isFile()) {
num = num + getDir.length();
}else {
num = num + getFileLength(getDir);
}
}
return num;
}
/*
* 如何从键盘接收文件夹路径
* 返回值类型:File
* 参数列表:
*/
public static File getDir() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入文件夹路径");
while(true) {
String len = sc.nextLine();
File file = new File(len);
if(!file.exists()) {
System.out.println("您输入的文件夹路径不存在,请输入正确的文件夹路径:");
}else if(file.isFile()) {
System.out.println("您输入的是文件路径,请输入正确的文件夹路径:");
}else {
return file;
}
}
}
}
案例2:从键盘接收一个文件夹路径,删除该文件夹
package com.digui.test;
import java.io.File;
public class Test02 {
/**
* 需求:从键盘接收一个文件夹路径,删除该文件夹
* 从键盘接收一个文件夹路径
* 1.创建键盘录入对象
* 2.定义一个无限循环,循环控制条件是输入了正确的文件夹路径
* 3.将键盘录入的结果存储并封装成File对象
* 4.对File对象判断,是否是正确的文件夹路径
* 5.如果是文件夹路径,就将文件夹路径返回
*
* 删除文件夹
* 1.获取该文件夹下的所有文件和文件夹
* 2.遍历数组
* 3.判断是文件就直接删除
* 4.如果是文件夹就递归调用
* 5.循环结束后.把空文件删除
*/
public static void main(String[] args) {
//调用键盘录入文件夹路径方法
File file = Test01.getDir();
//调用删除方法
deleteFile(file);
}
/*
* 删除文件夹
* 返回值类型:void
* 参数列表:File file
*/
public static void deleteFile(File file) {
//1.获取该文件夹下的所有文件和文件夹
File[] subFiles = file.listFiles();
//遍历数组
for(int i=0; i<subFiles.length; i++) {
//3.判断是文件就直接删除
if(subFiles[i].isFile()) {
subFiles[i].delete();
//4.如果是文件夹就递归调用
}else {
deleteFile(subFiles[i]);
}
}
//5.循环结束后.把空文件删除
file.delete();
}
}
案例3:键盘接收两个文件夹路径,把其中一个文件夹中所有内容拷贝到另一个文件夹中
package com.digui.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test03 {
/**
* @param args
* @throws IOException
*需求:从键盘接收两个文件夹路径,把其中一个文件夹中所有内容拷贝到另一个文件夹中
*分析:
*1.首先要在目标文件夹中创建一个原文件夹
*2.创建此抽象路径名指定的目录
*3.获取原文件夹中所有的文件和文件夹,存储在在File数组中
*4.遍历数组
*5.如果是文件就用IO流进行读写操作
*6.如果是文件夹就递归调用
*
*问题:原则上是不能在同一个文件夹中进行拷贝本文件夹的操作的,这样会产生无限拷贝操作,直到最后内存溢出电脑蓝屏
* 所有在代码中要加入判断操作,如果是同文件夹拷贝就不让程序执行
*/
public static void main(String[] args) throws IOException {
//调用键盘录入文件夹路径方法
File src = Test01.getDir();
File dest = Test01.getDir();
if(src.getName().equals(dest.getName())){
System.out.println("目标文件夹是源文件的子文件夹");
}else {
//调用拷贝方法
copyFiles(src,dest);
}
}
public static void copyFiles(File src, File dest) throws IOException {
//在目标文件夹中创建原文件夹
File newFiles = new File(dest, src.getName());
newFiles.mkdir();
//获取原文件夹中所有的文件和文件夹,存储在File数组中
File[] subFiles = src.listFiles();
//遍历数组
for (File subFile : subFiles) {
//如果是文件就用IO流读写
if(subFile.isFile()) {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(subFile));
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(new File(newFiles,subFile.getName())));
byte[] arr = new byte[1024*8];
int len;
while((len=bis.read(arr))!=-1) {
bos.write(arr, 0, len);
}
bos.close();
bis.close();
//如果是文件夹就递归调用,必须弄清楚原文件和目标文件的位置
}else {
copyFiles(subFile, newFiles);
}
}
}
}
案例4:从键盘接收一个文件夹路径,把文件夹中的所有文件和文件夹的名字按层级打印
package com.digui.test;
import java.io.File;
public class Test04 {
/**
* @param args
* 需求:从键盘接收一个文件夹路径,把文件夹中的所有文件和文件夹的名字按层级打印
*/
public static void main(String[] args) {
//调用键盘录入文件夹路径方法
File file = Test01.getDir();
//调用打印方法
printDir(file,0);
}
//问题,并没有对"\t"进行重复操作,只进行了一次
public static void printDir(File file,int n) {
File[] subFiles = file.listFiles();
for (File subFile : subFiles) {
for(int i=0; i<=n; i++) {
System.out.print("\t");
}
System.out.println(subFile.getName());
if(subFile.isDirectory()) {
printDir(subFile,n+1);
}
}
}
}