先来看张图:
这个很像Java的UML图。勉强按UML图来理解下。这张图里有几个比较有趣的地方:
接下来挨个解释下。
trait翻译为中文意思是“特质”。在trait中封装了方法和字段的定义,并且可以多继承,这个类似于Java中的接口。但是和Java中的接口不同的是:scala中trait的定义除了使用关键字trait外,其他与类定义无异。
关于trait先就说这些,以后再慢慢说。
这里让我觉得比较奇怪的是scala.collection.immutable.HashSet和scala.collection.immutable.Set的关系居然是继承。我找了张Java中集合的类图,来看一下:
与上图比较可以看到有明显的不同:在Java中常用的集合类通常是实现指定的接口,是implements而非是extends。也许scala中并没有implements这样的机制。不管怎样,这个都只能留到以后见分晓了。
Scala为Set提供了两个trait,分别是可变和不可变的。因此如果想要使用scala中的HashSet,可以根据需要选择可变与不可变的具体实现类。默认的Set是不可变的,需要使用可变Set时需要使用import关键字显式引入或者使用全限定类名。看一下下面这段代码:
def testImmutableSet(){ var immutableSet = Set("zhyea.com", "robin") immutableSet+="zhang" println(immutableSet) } def testMutableSet(){ var mutableSet = scala.collection.mutable.Set("zhyea.com", "robin") mutableSet+="zhang" println(mutableSet) }
上面的第一个方法使用了不可变Set,第二个方法使用了可变Set,执行结果都差不多(请忽略第一行的“Hello World!”):
虽然结果差不多,但是还是有些不同的:不可变Set中没有提供“+=”这样的方法,可变Set提供了“+=”方法,不可变Set的“+=”运算实际上是Set1 = Set1 + Set2。至于为什么Set中的元素输出顺序会不一样,还是留着以后去分析好了(现在我看Scala的SDK源码有种看天书的感觉)。
目前还有一点让我比较疑惑,就是可变Set和不可变Set的“+”方法,可变Set调用“+”方法后集合的长度居然没有发生变化:
def testImmutableSet(){ var immutableSet = Set("zhyea.com", "robin") immutableSet + "zhang" println(immutableSet) } def testMutableSet(){ var mutableSet = scala.collection.mutable.Set("zhyea.com", "robin") mutableSet + "zhang" println(mutableSet) }
执行结果:
看了下“+”方法的描述,是创建了一个新的对象:
/** Creates a new set consisting of all the elements of this set and `elem`. * * $addDuplicates * * @param elem the element to add. * @return a new set consisting of elements of this set and `elem`. */ @migration("`+` creates a new set. Use `+=` to add an element to this set and return that set itself.", "2.8.0") override def + (elem: A): This = clone() += elem
Map和Set类似,采用继承机制和trait提供了两种版本的Map:
可变的Map在scala.collection.mutable里面,不可变的Map在scala.collection.immutable里面。
下面是一段可变Map的使用示例:
val mutableMap = scala.collection.mutable.Map[Int, String](); mutableMap += (1 -> "zhyea.com") mutableMap += (2 -> "robin") println(mutableMap(2))
在代码的第一行里使用可变Map的全限定类名定义了一个val变量(因为使用的Map是可变的,所以可以将变量定义为val类型)。第二行使用了“->”和“+=”方法为mutableMap变量添加元素。前面提过Scala编译器把1->”zhyea.com”这样的二元操作符表达式转译为(1).->”zhyea.com”,即在Int型的值1上调用它的“->”方法,并传入参数“zhyea.com”,这个方法的返回值是一个包含键值对的二元元组。然后这个二元元组会被传递给mutableMap的“+=”方法。看一下最后的打印结果,这里输出了键值为2的值:
不可变Map是缺省的可以直接使用,看一下下面这段代码:
val immutableMap = Map(1 -> "zhyea.com", 2 -> "robin") println(immutableMap(2))
再来看一下这两次Map的初始化。第一次在定义mutableMap的时候显式指明了类型参数;第二次因为提供了初始化元素,所以scala编译器可以通过元素推断出immutableMap的类型参数。第一次的mutableMap也可以这样定义:
val mutableMap = scala.collection.mutable.Map(3 -> "zhyea.com");
就这样。
###########