繁体   English   中英

程序由于递归而变慢

[英]Program slowing down due to recursion

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

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

程序由于递归而变慢

不,不是。 递归不会使事情变慢。 较差的算法和不良的编码会使事情变慢。

例如,您呼叫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);
            }
        }
    }

(从Java 7开始)有一个内置的方式来执行此操作,即Files.walkFileTree ,它效率更高,并且不需要重新发明轮子。 它为找到的每个条目调用FileVisitor FileVisitor页面上有几个示例,可以帮助您入门。

重新发明轮子是否有特定原因? 如果您不介意,请使用

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

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

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

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

简而言之,您可能会遇到与软件编写方式无关的硬件限制。 简短一点:如果要提高性能,请不要包含大量文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM