我尝试使用文件名(字符串)制作某种方便的类(下面)来保存文件夹并获取文件。这项工作如我所料,但我不明白的一件事是地图部分Map(folder.listFiles map {file => file.getName -> file}:_*)
。
我将:_*
放在那里以防止某种类型不兼容,但我不知道它真正做了什么。此外,什么是_*
,我可以替换更具体的内容吗?
感谢
class FolderAsMap (val folderName:String){
val folder = new File(folderName)
private val filesAsMap: Map[String, File] = Map(folder.listFiles map
{file => file.getName -> file}:_*)
def get(fileName:String): Option[File] = {
filesAsMap.get(fileName)
}
}
答案 0 :(得分:8)
:_ *是正确的。或者,您可以使用toMap:
folder.listFiles map {file => file.getName -> file}.toMap
Map(...)
是对象apply
中的方法Map
:def apply [A, B] (elems: (A, B)*): Map[A, B]
。它有一个重复的参数。预计将使用多个参数调用它。 :_ *用于表示您将所有参数作为一个Seq参数传递。
避免含糊不清。在java中,(其中等效的varargs是数组而不是Seqs)可能存在歧义,如果方法f(Object... args)
并且用f(someArray)
调用它,则可能意味着args只有一个项目, someArray(所以f只接收一个元素的数组,其someArray
),或args为someArray
,f直接接收someArray
。 Java选择第二个版本。在scala中,使用更丰富的类型系统和Seq
而不是Array
,歧义可能会更频繁地出现,并且规则是你总是必须写:_ *将所有参数作为一个,甚至当没有歧义时,就像在这里一样,而不是一个复杂的规则来判断何时存在实际的歧义。
答案 1 :(得分:2)
_*
使编译器将folder.listFiles map { file => file.getName -> file}
的每个元素作为自己的参数传递给Map
,而不是将它作为一个参数传递。
在这种情况下,map
函数会创建Array
(因为folder.listFiles
会返回该类型)。所以,如果你写:
val files = folder.listFiles map { file => file.getName -> file }
...返回的类型为Array[(String, File)]
。要将其转换为Map
,您需要使用files
将_*
逐个传递给maps构造函数(或使用@didierd写的方法toMap
):
val filesAsMap = Map(files : _*)