java中常见的递归使用场景

一、递归概述

程序调用自身的编程技巧称为递归.递归作为一种算法在程序设计语言中广泛应用。
递归需具备的条件:

  1. 子问题须与原始问题为同样的事,且更为简单;
  2. 不能无限制调用本身,须有个出口,化简为非递归状态处理;
  3. 递归的次数不能太多,否则容易造成栈内存溢出(java.lang.StackOverflowError);
  4. 构造方法不能递归调用。

二、计算任意正整数的阶乘

由于受到intlong取值范围的限制,将数据转换成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;
            }
        }
    }
}

五、拷贝文件夹

使用BufferedInputStreamBufferedOutputStream高效的拷贝文件夹。

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;
            }
        }
    }
}

六、小结

  1. 其实拷贝文件夹还有更加简单的方法,org.apache.commons.io.FileUtils工具类有一个方法copyDirectoryToDirectory(File source,File target)可以直接完成。具体代码如:FileUtils.copyDirectoryToDirectory(getDir(), getDir());
  2. 参考文献:维基百科、veda等。
  3. 遍历二叉树以后补充。

你可能感兴趣的:(java中常见的递归使用场景)