我是Scala的新手,想知道使用以下三种方式初始化Map数据结构有什么区别:
private val currentFiles: HashMap[String, Long] = new HashMap[String, Long]()
private val currentJars = new HashMap[String, Long]
private val currentVars = Map[String, Long]
答案 0 :(得分:3)
您的问题有两个不同的部分。
首先,使用显式类型(案例1和案例2)之间的区别适用于任何类,不一定是容器。
val x = 1
这里的类型不明确,编译器会尝试使用类型推断来解决它。 x
的类型为Int
。
val x: Int = 1
与上述相同,但现在明确说明。如果=
右边的任何内容无法转换为Int,则会出现编译错误。
val x: Any = 1
这里我们仍将存储1
,但变量的类型将是父类,使用多态。
问题的第二部分是初始化。基本初始化与java中一样:
val x = new List[Int]()
这将调用类构造函数并返回确切类的新实例。
现在,有一个名为.apply
的特殊方法,您可以使用括号来定义和调用,如下所示:
val x = Seq[Int]()
这是一个快捷方式:
val x = Seq.apply[Int]()
请注意,这是Seq
对象上的一个函数。返回类型是函数想要的任何东西,它只是另一个函数。也就是说,它主要用于返回给定类型的新实例,但是没有保证,您需要查看函数文档以确保合同。
也就是说,在val x = Map[String, Long]()
的情况下,实现返回immutable.HashMap[String, Long]
的实际实例,这是一种默认的Map
实现。
答案 1 :(得分:2)
Map
和HashMap
几乎相同,但不完全相同。
Map是特质,HashMap是一个类。尽管在幕后他们可能是同一件事(scala.collection.immutable.HashMap)(稍后会详细介绍)。
使用时
private val currentVars = Map[String, Long]()
您获得了Map
个实例。在scala中,()
是一个糖,你实际上是在调用object Map的apply()
方法。这相当于:
private val currentVars = Map.apply[String, Long]()
使用
private val currentJars = new HashMap[String, Long]()
你得到一个HashMap实例。
在第三个声明中:
private val currentJars: HashMap[String, Long] = new HashMap[String, Long]()
你只是不再依赖type inference了。这与第二个语句完全相同:
private val currentJars: HashMap[String, Long] = new HashMap[String, Long]()
private val currentJars = new HashMap[String, Long]() // same thing
关于类型推断,我建议你使用类型推断。在这种情况下,恕我直言,它从代码中删除了实际上不需要的详细程度。但如果您真的错过了类似java代码,那么请包含类型:)。
现在,关于两个构造函数......
简短回答
你应该总是使用Map()
:它更短,已经导入并返回一个特征(如java界面)。最后一个原因很好,因为当你传递这个Map时,你不会依赖于实现细节,因为Map
只是你想要或需要的接口。
另一方面,HashMap
是一种实现。
答案很长
Map
并非总是HashMap
。
如在 Scala编程中所见,Map.apply[K, V]()
可以返回一个不同的类,具体取决于您传递给它的键值对(ref):
Number of elements Implementation
0 scala.collection.immutable.EmptyMap
1 scala.collection.immutable.Map1
2 scala.collection.immutable.Map2
3 scala.collection.immutable.Map3
4 scala.collection.immutable.Map4
5 or more scala.collection.immutable.HashMap
当你有少于5个元素时,你会为每个小集合获得一个特殊的类,当你有一个空的Map时,你会得到一个单例对象。
这主要是为了获得更好的表现。
您可以在repl中尝试:
import scala.collection.immutable.HashMap
val m2 = Map(1 -> 1, 2 -> 2)
m2.isInstanceOf[HashMap[Int, Int]]
// false
val m5 = Map(1 -> 1, 2 -> 2, 3 -> 3, 4 -> 4, 5 -> 5, 6 -> 6)
m5.isInstanceOf[HashMap[Int, Int]]
// true
如果你真的很好奇,你甚至可以看看source code。
因此,即使是表现,你也应该坚持使用Map()
。