1

我有一段代码,并且很难理解这种递归模式。

private void indexDirectory(IndexWriter indexWriter, File dataDirectory,
                            String suffix) throws IOException {

    System.out.println("Data directory before: " + dataDirectory.getName());
    File[] files = dataDirectory.listFiles();

    for (File file : files) {
        System.out.println("File name : " + file.getName());
        if (file.isDirectory()) {
            indexDirectory(indexWriter, file, suffix);
        } else {
            indexFileWithIndexWriter(indexWriter, file, suffix);
        }
    }
    System.out.println("Data directory : " + dataDirectory.getName());
}

dataDirectory 包含一个目录的路径,其中包含多个子目录和文件。

所以 files[] 数组看起来像,

C:\projects\test\.classpath, 
C:\projects\test\.project, 
C:\projects\test\.settings, 
C:\projects\test\build, 
C:\projects\test\build.xml, 
C:\projects\test\dist, 
C:\projects\test\src, 
C:\projects\test\WebContent

.classpath.project是文件,而.settings是一个包含 4 个文件的目录。因此,当第三次迭代.settings目录被调用时,其中包含 4 个文件。因为 .settings 是一个目录,所以 file.isDirectory真实 的,并且相同的方法 (indexDirectory) 将使用最新的参数值调用。所以dataDirectory值被.settings取代。当代码执行进入循环时,它将转到else部分,因为它在.settings目录中找到了文件。

一旦它迭代了 4 次(因为它只有 4 个文件),它应该完成循环。

但奇怪的是 dataDirectory值被它所拥有的旧值替换,并且它开始调用数组中先前存在的下一项(即构建目录)。

有人可以解释我为什么会这样,而没有完成循环..我希望我解释清楚,如果没有请问我。

非常感谢。

4

4 回答 4

3

当方法indexDirectory第一次被调用时,它里面有 8 个文件(包括目录)。

因此,您的 for 循环for (File file : files) {将至少迭代 8 次。(一个)

现在,在 8 个文件中,找到了.settings目录。并且您正确理解它会indexDirectory使用 dataDirectory = .settings 进行递归调用。此时,状态(A)有 5 次迭代待处理

当递归调用完成时,控件到达状态(A),第 4 次迭代以 dataDirectory = build 开始。

堆栈帧如下:

在此处输入图像描述

在第 2 帧完成后,第 1 帧将恢复执行。

于 2012-10-22T11:30:49.020 回答
1

这就是递归的工作原理。在遍历顶级目录时,一切正常,直到循环遇到一个目录。当它遇到一个目录时,它会进入一个更深的循环,但它知道它还没有完成外循环。一旦它完成了内循环(以及它内部的任何进一步的内循环),它就会返回并完成外循环。

想象一下,你在一个有很多门的房间里。当您转动门上的旋钮时,会弹出一面旗帜。其中一些门通向其他房间(屋内更深处),但大多数只是挂在墙上。您必须转动每个门把手上的旋钮。如果它打开到另一个房间,你也必须转动每个门上的旋钮。当内室的所有旗帜都升起时,您可以回到外间并完成旋转旋钮,直到所有旗帜都升起。当所有的旗帜都升起并且你回到最外面的房间时,你的工作就完成了。

hth

于 2012-10-22T11:32:05.987 回答
0

您正在递归调用 indexDirectory。因此,在完成更深的目录(在此示例中为 .settings )后,它将继续完成循环。

于 2012-10-22T11:34:45.677 回答
0

一旦它迭代了 4 次(因为它只有 4 个文件),它应该完成循环。

但奇怪的是 dataDirectory 值被它所拥有的旧值替换,并且它开始调用数组中先前存在的下一项(即构建目录)。

这正是递归应该如何工作的。

您在某种程度上是对的,一旦调用indexDirectory(?, ".settings", ?)已经看到四个文件,它应该停止循环并终止该方法。就是这样,事实上这就是发生的事情。该方法在此时完成,控制权返回给它的调用者。

然而,呼叫者是另一个indexDirectory“更高”级别的呼叫。 调用正在遍历 中的项目C:\projects\test\,并且刚刚完成.settings对它遇到的项目的处理。因此,一旦该方法返回,它就会从它(递归地)调用之前的位置indexDirectory继续.settings

因此,正如人们所期望的那样,它随后被编入索引C:\projects\test\build,依此类推。

为了进一步澄清,价值dataDirectory并没有完全被替换。实际发生的是这个参数同时有两个副本——两个嵌套方法调用中的每一个都有一个。内在。递归方法有值.settings,外层方法有test。一旦内部方法访问了它的四个文件并返回,控制权就返回到外部方法——它(仍然)有一个值testfor dataDirectory

于 2012-10-22T11:29:57.163 回答