递归:尽量减少不必要的递归消耗方式

能用迭代的尽量不用递归,在使用递归的时候写发也很重要,要尽量减少不必要的再次递归调用:

E.G.:

這是一个递归删除文件夹的例子:

写法1:

private static boolean deleteDir (File dir) {//删除文件夹
        if (dir.isDirectory ()) {//是文件夹就列表递归删除
            File[] files = dir.listFiles ();
            for (File file : files) {
                    deleteDir (file);
            }
        }
        dir.delete ();//是文件夹通过上面的递归就已经删空了,最后不管是空文件夹还是文件都删除
        return true;
    }

写法2:

  private static boolean deleteDir (File dir) {//删除文件夹
        if (dir.isDirectory ()) {//是文件夹就列表递归删除
            File[] files = dir.listFiles ();
            for (File file : files) {
                if (file.isDirectory ()) {//添加if的判断比直接 deleteDir (file); 好在是文件就直接删除,减少递归的消耗
                    deleteDir (file);
                } else {
                    file.delete ();
                }
            }
        }
        dir.delete ();//是文件夹通过上面的递归就已经删空了,最后不管是空文件夹还是文件都删除
        return true;
    }

写法1和写法2 都能实现,但是写法1在遍历files的时候把每一个file都进行了一次递归调用,总的调用次数为文件数n+文件夹数m

而写法2对每一个file进行一次判断,文件就直接删除,不再进行递归调用,只对文件夹进行调用,总的调用次数为文件夹数m

相对与每次递归调用的消耗来说,进行一次判断而取消一次递归,应该是很划算的.以后写递归的时候也要注意


再比如下面的copy的栗子:

写法1:

 private static boolean copyDir(File soc,File dsc) throws IOException {//copy soc目录的所有文件到dsc目录下
        File newDsc = new File (dsc,soc.getName ());//更新目标路径   %有构造方法支持上面的实现%
        if (soc.isFile ()) {//是文件就用流读写
            FileInputStream fis = new FileInputStream (soc);
            FileOutputStream fos = new FileOutputStream (newDsc);
            int len;
            byte[] arr = new byte[8192];
            while (( len = fis.read (arr) ) != - 1) {
                fos.write (arr,0,len);
            }
            fis.close ();
            fos.close ();
        } else {//是目录
            if (!newDsc.exists ()) {//目录不存在就创建目录
                newDsc.mkdirs ();
            }
            File[] files = soc.listFiles ();
            for (File file : files) {
                copyDir (file, newDsc);//递归copy file到加上文件名的新dsc目录下
            }
        }
        return true;
    }

写法2:

private static boolean copyDir(File soc,File dsc) throws IOException {//copy soc目录的所有文件到dsc目录下
        File newDsc = new File (dsc,soc.getName ());//更新目标路径   %有构造方法支持上面的实现%
            if (!newDsc.exists ()) {//目录不存在就创建目录
                newDsc.mkdirs ();
            }
            File[] files = soc.listFiles ();
            for (File file : files) {
                if (file.isFile ()) {
                    FileInputStream fis = new FileInputStream (file);
                    FileOutputStream fos = new FileOutputStream (new File (newDsc,file.getName ()));
                    int len;
                    byte[] arr = new byte[8192];
                    while (( len = fis.read (arr) ) != - 1) {
                        fos.write (arr, 0, len);
                    }
                    fis.close ();
                    fos.close ();
                } else {
                    copyDir (file, newDsc);//递归copy file到加上文件名的新dsc目录下
                }
            }
        return true;
        }

同样也是都能实现,但是写法1在:
 for (File file : files) {
                copyDir (file, newDsc);//递归copy file到加上文件名的新dsc目录下
            }

這里把子目录下所有的目录包括文件都进行递归调用,文件也递归一次在该次递归中才判断是否是文件,而进行处理,这是很没有必要而且浪费的,应该和写法2一样在这里进行判断,对不需要递归解决的问题,当场解决,减少递归的调用次数和内存消耗,



综合今天的错误来看,貌似只要在调用递归之前,进行一次判定,把不需要进行递归的问题当场解决,就可以减少不必要的递归调用,

也就是说要把递归语句放在if-else块中

减少消耗,增加效率.(自我总结,有待验证!!!)

你可能感兴趣的:(java)