我是scala / java的新手,我试图理解下面的代码,它返回目录中的文件列表。 Function source
需要一个名为dir
的参数 - dir
一个File
或File
对象的类型?
它返回一个类型为file
的数组。
它在listFiles
上调用方法dir
。
最后一行是做什么的?
def getRecursiveListOfFiles(dir: File): Array[File] = {
val these = dir.listFiles
these ++ these.filter(_.isDirectory).flatMap(getRecursiveListOfFiles)
}
答案 0 :(得分:3)
此代码使用递归进行广度优先搜索。
File
可以是文件,也可以是目录。
代码dir.listFiles
列出目录中的所有文件。请记住,这将是一个文件和目录列表!
然后我们可以将最后一行分解为3个方面。这些可能很容易分开。
these.filter(_.isDirectory)
将返回需要搜索的目录列表。它会过滤掉文件。flatMap(getRecursiveListOfFiles)
获取此目录列表,并为每个目录调用getRecursiveListOfFiles
。然后,它会将这些结果展平为一个列表。++
将两个数组加在一起。我们将these
添加到递归调用的结果中。 flatMap
是关键所在。阅读它,以及它与map
功能的区别,以便完全了解正在发生的事情。
答案 1 :(得分:2)
简而言之:
these ++ these.filter(_.isDirectory).flatMap(getRecursiveListOfFiles)
基本上是:
val allSubDirectories:Array[Files] = these.filter(_.isDirectory)
allSubDirectories.flatMap(getRecursiveListOfFiles)
//i.e. for each sub-directory, again find all files in sub-directory
these ++ (files of all sub-directories)
//ultimately add files of sub-directory to the actual list
另一种理解的方法是:
def getAllFiles(dir: File): List[File] = {
val these = dir.listFiles.toList
these ::: these.filter(_.isDirectory).map(x => getAllFiles(x)).flatten
}
基本上相同的控制流,每个子目录,你得到一个所有文件的列表,然后到同一个列表,你添加子目录的文件。
答案 2 :(得分:1)
我打算试着指导您如何将此视为有人试图阅读一段未知代码。
上下文应该非常清楚File
可以是常规文件或目录。它不包含文件内容,但表示文件系统中的任何条目,您可以使用其他库命令打开该文件。出于此功能的目的,File
只是在它是一个目录的情况下恰好包含更多File
的内容,并且可以通过listFiles: List[Files]
方法访问这些内容。 。据推测,它还提供其他信息,以便getRecursiveListOfFiles
的原始调用者可以对结果列表执行某些操作。
同样通过上下文,these
显然是当前目录中的条目。
最后一行是最微妙的。但要将其细分,它会使these
中File
中的these
增加flatMap
,这恰好是目录。
要解释此步骤,List[File]
上flatMap[B](f: File => List[B]): List[B]
的签名可以被视为B
,其中getRecursiveListOfFiles
是类型变量。在这种情况下,因为递归传递了类型File => List[File]
的相同函数B
,File
只是flatMap(f: File => List[File]): List[File]
,所以我们可以想到这个特定的调用为flatMap
。
粗略地说,f
将函数f
应用于容器中的每个项目,其中map
需要返回相同类型的容器。 " flat"部分只是这些单独的容器被组合而不是嵌套的事实,这是{{1}}将要做的事情。这是允许函数以递归方式添加在其子目录中找到的所有文件的原因。很漂亮。
答案 3 :(得分:0)
你所画的区别是什么? dir
的类型为File
。
一组File
s,是。
它可能隐含地将these
转换为scala List
或Buffer
,这是令人困惑的部分(例如,它可能会导入scala.collection.JavaConversions._
- 最好使用JavaConverters
,这会使转化显式调用.asScala
或asJava
)。您可以在the scaladoc中找到++
,filter
和flatMap
的定义,这有助于了解发生了什么。
(注意:我的4.因为降价而成为3.()