面试2 --- 递归算法
1 例: 2 //求6的阶乘 3 public class DiGeiDome { 4 public static void main(String[] args) { 5 int sum = getSum(6); 6 System.out.println(sum); 7 } 8 9 public static int getSum(int n){//n=3 10 if (n==1) { 11 return 1; 12 }else{ 13 return n*getSum(n-1);//3*getSum(2);getSum(2)=2*getSum(1) 14 } 15 } 16 } 17
java中常见的递归使用场景
- 子问题须与原始问题为同样的事,且更为简单;
- 不能无限制调用本身,须有个出口,化简为非递归状态处理;
- 递归的次数不能太多,否则容易造成栈内存溢出(
java.lang.StackOverflowError
); - 构造方法不能递归调用。
二、计算任意正整数的阶乘
由于受到int
、long
取值范围的限制,将数据转换成BigInteger
包装类。但是受到电脑内存的限制,只能计算5000以内的正整数阶乘。
1 import java.math.BigInteger; 2 import java.util.Scanner; 3 4 public class Recursion_Demo1 { 5 6 public static void main(String[] args) { 7 Scanner sc = new Scanner(System.in); 8 System.out.println("求阶乘:"); 9 System.out.println(getFactorial(sc.nextInt())); 10 } 11 12 public static BigInteger getFactorial(int num) { 13 if(num == 1) { 14 return BigInteger.ONE; 15 } 16 return BigInteger.valueOf(num).multiply(getFactorial(num - 1)); 17 } 18 }
三、计算文件夹大小
由于File
类下length()
(返回值类型为long
型)方法只能统计文件的大小,没有方法直接统计文件夹的大小,需要使用递归的方法遍历到所有的文件,并累加,最终计算出文件夹大小。
1 import java.io.File; 2 import java.util.Scanner; 3 public class Recursion_Demo2 { 4 public static void main(String[] args) { 5 File dir = getDir(); 6 System.out.println(getFileLength(dir)); 7 System.out.println("统计完成!"); 8 } 9 10 public static File getDir() { 11 //1,创建键盘录入对象 12 Scanner sc = new Scanner(System.in); 13 System.out.println("请输入一个文件夹路径:"); 14 //2,定义一个无限循环 15 while(true) { 16 //3,将键盘录入的结果存储并封装成File对象 17 String line = sc.nextLine(); 18 File dir = new File(line); 19 //4,对File对象判断 20 if(!dir.exists()) { 21 System.out.println("您录入的文件夹路径不存在,请重新录入:"); 22 }else if(dir.isFile()) { 23 System.out.println("您录入的是文件路径,请重新录入:"); 24 }else { 25 //5,将文件夹路径对象返回 26 return dir; 27 } 28 } 29 } 30 public static long getFileLength(File dir) { 31 //1,定义一个求和变量 32 long len = 0; 33 //2,获取该文件夹下所有的文件和文件夹listFiles(); 34 File[] subFiles = dir.listFiles(); 35 //3,遍历数组 36 if(subFiles != null) { 37 for (File subFile : subFiles) { 38 //4,判断是文件就计算大小并累加 39 if(subFile.isFile()) { 40 len = len + subFile.length(); 41 //5,判断是文件夹,递归调用 42 }else { 43 len = len + getFileLength(subFile); 44 } 45 } 46 } 47 return len; 48 } 49 }
四、删除指定目录
File
类目录下boolean delete()
方法:删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则该目录必须为空才能删除。
因此只能通过遍历目录下所有的文件,并删除。
1 import java.io.File; 2 import java.util.Scanner; 3 public class Recursion_Demo3 { 4 public static void main(String[] args) { 5 File dir = getDir(); 6 deleteFile(dir); 7 System.out.println("删除成功!"); 8 } 9 public static void deleteFile(File dir) { 10 //1,获取该文件夹下的所有的文件和文件夹 11 File[] subFiles = dir.listFiles(); 12 //2,遍历数组 13 if(subFiles != null) { 14 for (File subFile : subFiles) { 15 //3,判断是文件直接删除 16 if(subFile.isFile()) { 17 subFile.delete(); 18 //4,如果是文件夹,递归调用 19 }else { 20 deleteFile(subFile); 21 } 22 } 23 } 24 //5,循环结束后,把空文件夹删掉 25 dir.delete(); 26 } 27 public static File getDir() { 28 //1,创建键盘录入对象 29 Scanner sc = new Scanner(System.in); 30 System.out.println("请输入一个文件夹路径:"); 31 //2,定义一个无限循环 32 while(true) { 33 //3,将键盘录入的结果存储并封装成File对象 34 String line = sc.nextLine(); 35 File dir = new File(line); 36 //4,对File对象判断 37 if(!dir.exists()) { 38 System.out.println("您录入的文件夹路径不存在,请重新录入:"); 39 }else if(dir.isFile()) { 40 System.out.println("您录入的是文件路径,请重新录入:"); 41 }else { 42 //5,将文件夹路径对象返回 43 return dir; 44 } 45 } 46 } 47 }
五、拷贝文件夹
使用BufferedInputStream
、BufferedOutputStream
高效的拷贝文件夹。
1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.util.Scanner; 8 public class Recursion_Demo4 { 9 public static void main(String[] args) throws IOException { 10 System.out.println("请录入源文件夹:"); 11 File src = getDir(); 12 System.out.println("请录入目标文件夹:"); 13 File target = getDir(); 14 if(src.equals(target)) { 15 System.out.println("无法拷贝"); 16 }else { 17 copy(src,target); 18 System.out.println("拷贝成功!"); 19 } 20 } 21 public static void copy(File src, File target) throws IOException { 22 //1,在目标文件夹中创建原文件夹 23 File newDir = new File(target, src.getName()); 24 newDir.mkdir(); 25 //2,获取原文件夹中所有的文件和文件夹,存储在File数组中 26 File[] subFiles = src.listFiles(); 27 //3,遍历数组 28 if(subFiles != null) { 29 for (File subFile : subFiles) { 30 //4,如果是文件就用io流读写 31 if(subFile.isFile()) { 32 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(subFile)); 33 BufferedOutputStream bos = new BufferedOutputStream 34 (new FileOutputStream(new File(newDir,subFile.getName()))); 35 36 int b = 0; 37 while((b = bis.read()) != -1) { 38 bos.write(b); 39 } 40 41 bis.close(); 42 bos.close(); 43 //5,如果是文件夹就递归调用 44 }else { 45 copy(subFile,newDir); 46 } 47 } 48 } 49 } 50 51 public static File getDir() { 52 //1,创建键盘录入对象 53 Scanner sc = new Scanner(System.in); 54 System.out.println("请输入一个文件夹路径:"); 55 //2,定义一个无限循环 56 while(true) { 57 //3,将键盘录入的结果存储并封装成File对象 58 String line = sc.nextLine(); 59 File dir = new File(line); 60 //4,对File对象判断 61 if(!dir.exists()) { 62 System.out.println("您录入的文件夹路径不存在,请重新录入:"); 63 }else if(dir.isFile()) { 64 System.out.println("您录入的是文件路径,请重新录入:"); 65 }else { 66 //5,将文件夹路径对象返回 67 return dir; 68 } 69 } 70 } 71 }
六、小结
- 其实拷贝文件夹还有更加简单的方法,
org.apache.commons.io.FileUtils
工具类有一个方法copyDirectoryToDirectory(File source,File target)
可以直接完成。具体代码如:FileUtils.copyDirectoryToDirectory(getDir(), getDir())
;