简体   繁体   English

奇怪的Java递归代码

[英]Strange Java Recursion Code

I have a code piece and really struggling hard to understand this recursion pattern. 我有一个代码片,并且很难理解这种递归模式。

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 there contains a path to a directory where it having several sub directories and files within it. dataDirectory包含一个目录的路径,其中有多个子目录和文件。

so the files[] array looks like, 所以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 and .project are files, whereas .settings is a directory contain 4 files. .classpath.project是文件,而.settings是一个包含4个文件的目录。 So when the third iteration going .settings directory is getting called, and it's having 4 files within it. 因此当第三次迭代进入.settings目录时,它的内部有4个文件。 since .settings is a directory, file.isDirectory is getting true and the same method (indexDirectory) will call with the newest parameter values. 因为.settings是一个目录, file.isDirectory变为 true ,并且相同的方法(indexDirectory)将使用最新的参数值调用。 So the dataDirectory value getting replaced by .settings . 所以dataDirectory值被.settings取代。 when the code execution comes in to the loop it will go to else part because its found files inside the .settings directory. 当代码执行进入循环时,它将转到else部分,因为它在.settings目录中找到了它的文件。

Once it iterated 4 times (because its having only 4 files), it suppose to finish the loop. 一旦迭代4次(因为它只有4个文件),它就会完成循环。

But strangely dataDirectory values getting replaced by the older value it had and it begin to call the next item there was in the array previously (which is build directory). 但奇怪的是, dataDirectory值被它所拥有的旧值替换,它开始调用之前在数组中的下一个项目(这是构建目录)。

Can someone explain me why its happening like that, without finishing the loop.. I hope I explained it clearly, if not please ask me. 有人可以解释我为什么会这样发生,而不是完成循环..我希望我能清楚地解释它,如果没有请问我。

Thank you very much. 非常感谢你。

When method indexDirectory is called very first time, it has 8 files (including directories) inside. 当第一次调用方法indexDirectory时,它里面有8个文件(包括目录)。

So, your for loop for (File file : files) { will iterate atleast 8 times. 因此,你的for循环for (File file : files) {将迭代至少8次。 (A) (一种)

Now, within 8 files, .settings is found which is directory. 现在,在8个文件中,找到.settings是目录。 and you understood correctly that it'll resursive-call indexDirectory with dataDirectory = .settings. 并且你正确理解indexDirectory使用dataDirectory = .settings调用indexDirectory At this point, 5 iterations are pending from state (A) 此时,状态(A)中有5次迭代正在等待

When, recursive call completes, the controls reaches to state (A) and 4th iteration starts with dataDirectory = build. 当递归调用完成时,控件到达状态(A) ,第四次迭代以dataDirectory = build开始。

The stack frames will be as follows: 堆栈帧如下:

在此输入图像描述

After Frame 2 completes, Frame 1 will resume its execution. 第2帧完成后,第1帧将恢复执行。

That is how recursion works. 这就是递归的工作原理。 While looping through the top level directory, everything goes ok, until the loop comes across a directory. 在循环访问顶级目录时,一切正常,直到循环遍历目录。 When it comes across a directory it enters a deeper loop, but it knows it hasn't finished the outer loop. 当它遇到一个目录时,它进入一个更深的循环,但它知道它还没有完成外部循环。 Once it's finished the inner loop (and any further inner loops inside it), it comes back out and finishes off the outer loop. 一旦它完成内部循环(以及其内部的任何其他内部循环),它就会返回并完成外部循环。

Imagine you're in a room with a lot of doors. 想象一下,你在一个有很多门的房间里。 When you turn the knob on a door, a flag pops up. 当您转动门上的旋钮时,会弹出一个标记。 Some of these doors open into other rooms (deeper inside the house), but most are just hanging on the wall. 其中一些门通向其他房间(房屋内部较深处),但大多数只是悬挂在墙上。 You have to turn the knob on each door handle. 你必须转动每个门把手上的旋钮。 If it opens into another room, you have to turn the knob on each of those doors too. 如果它通向另一个房间,你必须转动每个门上的旋钮。 When all the flags are up on the inner room, you can then go back to the outer room and finish turning knobs til all the flags are up. 当所有的旗帜都在内室时,你可以回到外面的房间并完成转动旋钮,直到所有的旗帜都朝上。 When all the flags are up and you are back at the outermost room, your job is done. 当所有旗帜都已启动并且您回到最外层的房间时,您的工作就完成了。

hth 心连心

Once it iterated 4 times (because its having only 4 files), it suppose to finish the loop. 一旦迭代4次(因为它只有4个文件),它就会完成循环。

But strangely dataDirectory values getting replaced by the older value it had and it begin to call the next item there was in the array previously (which is build directory). 但奇怪的是,dataDirectory值被它所拥有的旧值替换,它开始调用之前在数组中的下一个项目(这是构建目录)。

This is exactly how recursion is supposed to work. 这正是递归应该如何工作的原因。

You are right to some extent that once the invocation of indexDirectory(?, ".settings", ?) had seen the four files, it should have stopped looping over and terminated the method. 你在某种程度上是正确的,一旦调用indexDirectory(?, ".settings", ?)indexDirectory(?, ".settings", ?)看到了四个文件,它应该已经停止循环并终止该方法。 That is the case, and in fact this is what happened . 情况确实如此,事实上这就是发生的事情 The method finished at that point, and control returned to its caller. 该方法在该点完成,并且控制权返回给其调用者。

However the caller was another indexDirectory call one level "higher up". 然而,调用者是另一个indexDirectory调用一个级别“更高”。 This call was iterating over the items in C:\\projects\\test\\ , and had just finished dealing with the .settings item that it came across. 这个调用迭代了C:\\projects\\test\\ ,刚刚完成了它遇到的.settings项目的处理。 So once that method returned, it continued from where it was before it (recursively) called indexDirectory on .settings . 因此,一旦该方法返回,它就会继续从它之前(递归地)在.settings上调用indexDirectory

So, as one should expect, it then indexed C:\\projects\\test\\build , and so on. 因此,正如人们所期望的那样,它然后索引C:\\projects\\test\\build ,依此类推。

To clarify some more, the value of dataDirectory wasn't exactly being replaced . 为了澄清一些, dataDirectory的值并没有完全被替换 What actually happened was that there were two copies of this argument at once - one for each of the two nested method invocations. 实际发生的是,这个参数有两个副本 - 一个用于两个嵌套方法调用。 The inner. 内心的。 recursive method had the value .settings , and the outer method had test . 递归方法有值.settings ,外部方法有test Once the inner method visited its four files and returned, control went back to the outer method - which (still) had a value of test for dataDirectory . 一旦内部方法访问了它的四个文件并返回,控制就返回到外部方法 - 其中(仍然)具有dataDirectorytest值。

You are calling indexDirectory recursively. 您以递归方式调用indexDirectory。 Therefore, after it finished the deeper directory (in this example is .settings ) it will continue to finish the loop. 因此,在完成更深层目录(在此示例中为.settings)之后,它将继续完成循环。

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

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