Java 由于递归,程序速度减慢

Java 由于递归,程序速度减慢,java,performance,recursion,Java,Performance,Recursion,我正在尝试编写一个程序,将C:驱动器上的每个文件和文件夹名称添加到ArrayList中。代码运行得很好,但是由于大量的递归,它变得非常缓慢。代码如下: public static void updateFileDataBase() { ArrayList<String> currentFiles = new ArrayList<String>(); addEverythingUnder("C:/",currentFiles,new String[]{"St

我正在尝试编写一个程序,将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");
    }
}
公共静态void updateFileDataBase()
{
ArrayList currentFiles=新建ArrayList();
AdderyThingunder(“C:/”,currentFiles,新字符串[]{“SteamApps”,“AppData”});
用于(字符串名称:currentFiles)
System.out.println(名称);
}
私有静态void adderythingunder(字符串路径、ArrayList列表、字符串[]异常)
{
gc();
System.out.println(“搜索”+路径);
文件搜索=新文件(路径);
尝试
{
for(int i=0;i

我想知道我能做些什么来加快这个过程。提前感谢:)

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

,java.lang.String[],布尔值)

由于递归,程序速度减慢

不,不是。递归不会让事情变慢。糟糕的算法和糟糕的编码让事情变得缓慢

例如,您对处理的每个文件调用了四次
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);
            }
        }
    }
在Java7中,有一种内置的方法可以做到这一点,它效率更高,并且不再需要重新发明轮子。它为找到的每个条目调用一个。FileVisitor页面上有几个示例可以帮助您入门

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

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

典型的硬盘驱动器的寻道时间为8毫秒,如果查找和打开一个文件需要两次操作,那么每个文件的寻道时间为16毫秒。假设你有10000个文件,这至少需要160秒,不管你的代码有多高效。顺便说一句,如果你使用一个像样的SSD,这将需要大约1秒


简言之,您可能会达到硬件限制,这与您编写软件的方式无关。简短:如果您想要提高性能,请不要使用大量文件。

您尝试过碎片整理吗?你为什么要这么做呢?我敢打赌,你所做的大量字符串连接并没有提高程序的速度。使用StringBuilders可能会有所帮助。您最多调用了5次
search.list()。即使底层FS实现缓存了列表,它仍然必须每次构建结果列表,这对于大型目录来说是累加的。您只使用了一个元素,所以第一次保存它。为什么要麻烦使用ArrayList?使用某种类型的集合,这样你的.contains就可以在近似恒定的时间而不是线性时间内运行。或者更好的是,如果你不想仅仅列出它们的话,使用java 7。+1你已经在这里提到了一些真正有效的点,特别是缓存。正如我们所说,我正在实现一个基本的文件搜索,并将在有线程或没有线程的情况下对其进行基准测试。(我需要亲自看一下。情不自禁!:)上次我用C写的(运行在P41.7GHz,7200RPM硬盘上),我相信我已经注意到了一个不同。您的帖子提醒我的是,重新启动系统以清除任何磁盘缓存,否则会使结果出现偏差。@RaviThapliyal另一个选项是访问大于内存大小的数据集。重启是最好的方法。