0

我正在尝试编写一个程序,将 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");
    }
}

我想知道是否有什么我可以做的来加快这个过程。提前致谢 :)

4

4 回答 4

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);
            }
        }
    }
于 2013-05-16T04:01:20.090 回答
5

(从 Java 7 开始)有一种内置方法可以做到这一点,Files.walkFileTree,它效率更高,并且无需重新发明轮子。它为找到的每个条目调用FileVisitor。FileVisitor 页面上有几个示例可以帮助您入门。

于 2013-05-16T04:38:22.413 回答
2

重新发明轮子有什么特别的原因吗?如果你不介意请使用

http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FileUtils.html#listFiles(java.io.File , java.lang.String[], boolean)

于 2013-05-16T03:55:59.503 回答
1

由于大量的递归,它变得非常缓慢

虽然您的代码正如 EJP 所建议的那样效率很低,但我怀疑问题甚至更为基本。当您访问大量文件时,从磁盘读取需要花费一些时间(第一次,再次读取相同的文件,并且再次读取速度更快,因为它是缓存)对于 HDD 来说,打开文件也很慢。

典型的 HDD 的寻道时间为 8 毫秒,如果查找和打开文件需要两次操作,那么每个文件的查找时间为 16 毫秒。假设您有 10,000 个文件,无论您编写代码的效率如何,这至少需要 160 秒。顺便说一句,如果您使用像样的 SSD,这将需要大约 1 秒。

简而言之,您可能会遇到与您编写软件的方式无关的硬件限制。更短:如果你想要性能,不要有大量的文件。

于 2013-05-16T05:17:46.247 回答