我正在尝试编写一个程序,将我的C:驱动器上的每个文件和文件夹名称添加到ArrayList。代码工作正常,但由于大量的递归,它变得非常缓慢。这是代码:
public static void updateFileDataBase()
{
ArrayList<String> currentFiles = new ArrayList<String>();
addEverythingUnder("C:/",currentFiles,new String[]{"SteamApps","AppData"});
for(String name : currentFiles)
System.out.println(name);
}
private static void addEverythingUnder(String path, ArrayList<String> list, String[] exceptions)
{
System.gc();
System.out.println("searching " + path);
File search = new File(path);
try
{
for(int i = 0; i < search.list().length; i++)
{
boolean include = true;
for(String exception : exceptions)
if(search.list()[i].contains(exception))
include = false;
if(include)
{
list.add(search.list()[i]);
if(new File(path + "/" + search.list()[i]).isDirectory())
{
addEverythingUnder(path + "/" + search.list()[i],list,exceptions);
}
}
}
}
catch(Exception error)
{
System.out.println("ACCESS DENIED");
}
}
我想知道我能做些什么来加快这个过程。在此先感谢:)
答案 0 :(得分:5)
程序因递归而减慢
不,不是。递归不会让事情变得缓慢。糟糕的算法和糟糕的编码会让事情变得缓慢。
例如,您为处理的每个文件调用Files.list()
四次,以及每个目录一次。您可以通过每个目录执行一次来保存O(N):
for(File file : search.listFiles())
{
String name = file.getName();
boolean include = true;
for(String exception : exceptions)
if(name.contains(exception))
include = false;
if(include)
{
list.add(name);
if(file.isDirectory())
{
addEverythingUnder(file,list,exceptions);
}
}
}
答案 1 :(得分:5)
(从Java 7开始)有一种内置的方法,Files.walkFileTree,这样做效率更高,无需重新发明轮子。它为它找到的每个条目调用FileVisitor。 FileVisitor页面上有几个例子可以帮助您入门。
答案 2 :(得分:2)
是否有重新发明轮子的特殊原因? 如果您不介意请使用
http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FileUtils.html#listFiles(java.io.File,java.lang.String [],boolean)
答案 3 :(得分:1)
由于大量的递归,它会变得非常缓慢
虽然您的代码效率非常低,因为EJP建议,但我怀疑这个问题更为基本。当您访问大量文件时,这需要一些时间从磁盘读取(第一次,再次读取相同内容,并且再次快速,因为它是缓存)打开文件对于HDD来说也很慢。
典型的硬盘驱动器的查找时间为8毫秒,如果查找和打开文件需要两个操作,那么您每个文件的查找时间为16毫秒。假设您有10,000个文件,无论您制作代码的效率如何,这都需要至少160秒。顺便说一下如果使用合适的SSD,这将需要大约1秒钟。
简而言之,您可能会达到硬件限制,这与您编写软件的方式无关。更短:如果你想要表现,不要有大量的文件。