在scala中使用Map和map进行了解

时间:2011-11-04 07:18:22

标签: scala map

我尝试使用文件名(字符串)制作某种方便的类(下面)来保存文件夹并获取文件。这项工作如我所料,但我不明白的一件事是地图部分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)
  }
}

2 个答案:

答案 0 :(得分:8)

:_ *是正确的。或者,您可以使用toMap:

folder.listFiles map {file => file.getName -> file}.toMap

Map(...)是对象apply中的方法Mapdef 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 : _*)