java基础之--递归与递归遍历多级目录+综合递归小案例

递归是一种应用非常广泛的算法(或者编程技巧)。递归求解问题的分解过程,去的过程叫“递”,回来的过程叫“归”

1. 递归

  • 递归: 在一个方法内部对自身进行调用

递归需要满足三个条件

  • 一个问题的解可以分解为几个子问题的解
  • 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样
  • 存在递归终止条件

递归的缺陷

  • 简单的程序是递归的优点之一。但是递归调用会占用大量的系统堆栈,内存耗用多,在递归调用层次多是速度要比循环慢的多,所以在使用递归时要慎重

2. 递归案例-计算1~N的和

  • 分析: num的累和 = num + (num-1)的累和,所以可以把累和的操作定义成一个方法,递归调用
package recursion;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-14 9:21
 */
public class sum_1_N {
    public static void main(String[] args) {
        // 计算1~num的和 使用递归
        int num = 5;
        // 调用求和方法
        int sum = getSum(num);
        System.out.println(sum);

    }

    public static int getSum(int num){
        // 如果num为1 那么返回1
        if (num == 1){
            return 1;
        // 否则返回num + (num-1)的累计和 递归调用
        }else{
            return num+getSum(num-1);
        }

    }
}

代码执行图解

小贴士:递归一定要有条件限定,保证递归能够停止下来,次数不要太多,否则会发生栈内存溢出
在这里插入图片描述

3. 递归案例-求阶乘

  • 阶乘: 所有小于及等于该数的正整数的积
  • n的阶乘:n! = n * (n‐1) *...* 3 * 2 * 1
  • 分析: 这与累和类似,只不过换成了乘法运算,需要注意阶乘值符合int类型的范围
  • 推理得出: n! = n * (n - 1)!
package recursion;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-14 9:31
 */
public class Factorial {
    public static void main(String[] args) {

        int n = 3;
        int value = getValue(n);
        System.out.println("阶乘为: "+value);
    }

    public static int getValue(int n){
        // 1的阶乘为1
        if (n == 1){
            return 1;
        }

        // n 不为1 方法返回 n! = n*(n-1)!
        // 递归调用getValue方法
        return n * getValue(n - 1);

    }
}

4. 递归案例-打印多级目录

  • 分析: 多级目录的打印,就是当目录的嵌套。遍历之前,无从知道到底有多少级目录,所以我们还是要使用递归实现
package recursion;

import java.io.File;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-14 9:39
 */
public class TraversalFile {
    public static void main(String[] args) {
        File file = new File("D:\\softWare-all");
        printDir(file);
    }

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

5. 递归案例-文件搜索

搜索D:\\softWare-all目录下所有的.java文件

分析:

  • 目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录
  • 遍历目录时,获取的子文件,通过文件名称,判断是否符合条件
package recursion;

import java.io.File;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-14 9:39
 */
public class TraversalFile {
    public static void main(String[] args) {
        File file = new File("D:\\softWare-all");
        printDir(file);
    }

    public static void printDir(File dir){
        // 获取子文件和目录
        File[] files = dir.listFiles();
        /*
        * 判断: 是文件时,打印绝对路径
        *       是目录时,继续调用打印目录方法,形成递归
        * */
        for (File file : files) {
            if (file.isFile()){
                /* 如果是.java文件 那么判断文件名字输出绝对路径*/
                if (file.getName().endsWith(".java")){
                    System.out.println("文件名: "+file.getAbsolutePath());
                }
            }else {
                printDir(file);
            }
        }
    }
}

5.1 文件过滤器优化

  • java.io.FileFilter 是一个接口,是File的过滤器。 该接口的对象可以传递给File类的 listFiles(FileFilter) 作为参数, 接口中只有一个方法
  • boolean accept(File pathname): 测试pathname是否应该包含在当前File目录中,符合则返回true

分析:

  • 接口作为参数,需要传递子类对象,重写其中方法。我们选择匿名内部类方式,比较简单
  • accept 方法,参数为File,表示当前File下所有的子文件和子目录。保留住则返回true,过滤掉则返回 false,要么是java文件,要么是目录,继续遍历
  • 通过过滤器的作用, listFiles(FileFilter) 返回的数组元素中,子文件对象都是符合条件的,可以直接打印。
package recursion;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.io.File;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-14 9:55
 */
public class FileFilter {
    public static void main(String[] args) {
        File file = new File("D:\\softWare-all");
        printDir(file);
    }

    public static void printDir(File dir){
        // 匿名内部类 创建过滤器子类对象
        File[] files = dir.listFiles(new java.io.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 {
                printDir(file);
            }

        }
    }
}

5.2 lambda优化

  • 分析:FileFilter 是只有一个方法的接口,因此可以用lambda表达式简写
  • lambda表达式如果不太理解请参考我这篇文章: lambda表达式传送门
package recursion;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.io.File;

/**
 * @Description
 * @auther 宁宁小可爱
 * @create 2020-01-14 9:55
 */
public class FileFilter {
    public static void main(String[] args) {
        File file = new File("D:\\softWare-all");
        printDir(file);
    }

    public static void printDir(File dir){
        // 使用lambda表达式优化 只有一个参数省略小括号 return一个语句 省略大括号和return关键字
        File[] files = dir.listFiles(pathname ->  pathname.getName().endsWith(".java") || pathname.isDirectory());

        // 循环打印
        for (File file : files) {
            if (file.isFile()){
                System.out.println("文件名: "+file.getAbsolutePath());
            }else {
                printDir(file);
            }

        }
    }
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叫我三胖哥哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值