能用迭代的尽量不用递归,在使用递归的时候写发也很重要,要尽量减少不必要的再次递归调用:
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块中
减少消耗,增加效率.(自我总结,有待验证!!!)