一、递归概述
程序调用自身的编程技巧称为递归.递归作为一种算法在程序设计语言中广泛应用。
递归需具备的条件:
- 子问题须与原始问题为同样的事,且更为简单;
- 不能无限制调用本身,须有个出口,化简为非递归状态处理;
- 递归的次数不能太多,否则容易造成栈内存溢出(
java.lang.StackOverflowError
); - 构造方法不能递归调用。
二、计算任意正整数的阶乘
由于受到int
、long
取值范围的限制,将数据转换成BigInteger
包装类。但是受到电脑内存的限制,只能计算5000以内的正整数阶乘。
import java.math.BigInteger;
import java.util.Scanner;
public class Recursion_Demo1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("求阶乘:");
System.out.println(getFactorial(sc.nextInt()));
}
public static BigInteger getFactorial(int num) {
if(num == 1) {
return BigInteger.ONE;
}
return BigInteger.valueOf(num).multiply(getFactorial(num - 1));
}
}
三、计算文件夹大小
由于File
类下length()
(返回值类型为long
型)方法只能统计文件的大小,没有方法直接统计文件夹的大小,需要使用递归的方法遍历到所有的文件,并累加,最终计算出文件夹大小。
import java.io.File;
import java.util.Scanner;
public class Recursion_Demo2 {
public static void main(String[] args) {
File dir = getDir();
System.out.println(getFileLength(dir));
System.out.println("统计完成!");
}
public static File getDir() {
//1,创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个文件夹路径:");
//2,定义一个无限循环
while(true) {
//3,将键盘录入的结果存储并封装成File对象
String line = sc.nextLine();
File dir = new File(line);
//4,对File对象判断
if(!dir.exists()) {
System.out.println("您录入的文件夹路径不存在,请重新录入:");
}else if(dir.isFile()) {
System.out.println("您录入的是文件路径,请重新录入:");
}else {
//5,将文件夹路径对象返回
return dir;
}
}
}
public static long getFileLength(File dir) {
//1,定义一个求和变量
long len = 0;
//2,获取该文件夹下所有的文件和文件夹listFiles();
File[] subFiles = dir.listFiles();
//3,遍历数组
if(subFiles != null) {
for (File subFile : subFiles) {
//4,判断是文件就计算大小并累加
if(subFile.isFile()) {
len = len + subFile.length();
//5,判断是文件夹,递归调用
}else {
len = len + getFileLength(subFile);
}
}
}
return len;
}
}
四、删除指定目录
File
类目录下boolean delete()
方法:删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则该目录必须为空才能删除。
因此只能通过遍历目录下所有的文件,并删除。
import java.io.File;
import java.util.Scanner;
public class Recursion_Demo3 {
public static void main(String[] args) {
File dir = getDir();
deleteFile(dir);
System.out.println("删除成功!");
}
public static void deleteFile(File dir) {
//1,获取该文件夹下的所有的文件和文件夹
File[] subFiles = dir.listFiles();
//2,遍历数组
if(subFiles != null) {
for (File subFile : subFiles) {
//3,判断是文件直接删除
if(subFile.isFile()) {
subFile.delete();
//4,如果是文件夹,递归调用
}else {
deleteFile(subFile);
}
}
}
//5,循环结束后,把空文件夹删掉
dir.delete();
}
public static File getDir() {
//1,创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个文件夹路径:");
//2,定义一个无限循环
while(true) {
//3,将键盘录入的结果存储并封装成File对象
String line = sc.nextLine();
File dir = new File(line);
//4,对File对象判断
if(!dir.exists()) {
System.out.println("您录入的文件夹路径不存在,请重新录入:");
}else if(dir.isFile()) {
System.out.println("您录入的是文件路径,请重新录入:");
}else {
//5,将文件夹路径对象返回
return dir;
}
}
}
}
五、拷贝文件夹
使用BufferedInputStream
、BufferedOutputStream
高效的拷贝文件夹。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Recursion_Demo4 {
public static void main(String[] args) throws IOException {
System.out.println("请录入源文件夹:");
File src = getDir();
System.out.println("请录入目标文件夹:");
File target = getDir();
if(src.equals(target)) {
System.out.println("无法拷贝");
}else {
copy(src,target);
System.out.println("拷贝成功!");
}
}
public static void copy(File src, File target) throws IOException {
//1,在目标文件夹中创建原文件夹
File newDir = new File(target, src.getName());
newDir.mkdir();
//2,获取原文件夹中所有的文件和文件夹,存储在File数组中
File[] subFiles = src.listFiles();
//3,遍历数组
if(subFiles != null) {
for (File subFile : subFiles) {
//4,如果是文件就用io流读写
if(subFile.isFile()) {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(subFile));
BufferedOutputStream bos = new BufferedOutputStream
(new FileOutputStream(new File(newDir,subFile.getName())));
int b = 0;
while((b = bis.read()) != -1) {
bos.write(b);
}
bis.close();
bos.close();
//5,如果是文件夹就递归调用
}else {
copy(subFile,newDir);
}
}
}
}
public static File getDir() {
//1,创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个文件夹路径:");
//2,定义一个无限循环
while(true) {
//3,将键盘录入的结果存储并封装成File对象
String line = sc.nextLine();
File dir = new File(line);
//4,对File对象判断
if(!dir.exists()) {
System.out.println("您录入的文件夹路径不存在,请重新录入:");
}else if(dir.isFile()) {
System.out.println("您录入的是文件路径,请重新录入:");
}else {
//5,将文件夹路径对象返回
return dir;
}
}
}
}
六、小结
- 其实拷贝文件夹还有更加简单的方法,
org.apache.commons.io.FileUtils
工具类有一个方法copyDirectoryToDirectory(File source,File target)
可以直接完成。具体代码如:FileUtils.copyDirectoryToDirectory(getDir(), getDir())
; - 参考文献:维基百科、veda等。
- 遍历二叉树以后补充。