转载

Scala学习8 – Set和Map

概述

先来看张图:

Scala学习8 – Set和Map

这个很像Java的UML图。勉强按UML图来理解下。这张图里有几个比较有趣的地方:

  • 一个新的概念——trait;
  • Set和Set、Set和HashSet全部都是继承关系;
  • 提供了immutable和mutable两套集合方案。

接下来挨个解释下。

trait

trait翻译为中文意思是“特质”。在trait中封装了方法和字段的定义,并且可以多继承,这个类似于Java中的接口。但是和Java中的接口不同的是:scala中trait的定义除了使用关键字trait外,其他与类定义无异。

关于trait先就说这些,以后再慢慢说。

关于继承

这里让我觉得比较奇怪的是scala.collection.immutable.HashSet和scala.collection.immutable.Set的关系居然是继承。我找了张Java中集合的类图,来看一下:

Scala学习8 – Set和Map

与上图比较可以看到有明显的不同:在Java中常用的集合类通常是实现指定的接口,是implements而非是extends。也许scala中并没有implements这样的机制。不管怎样,这个都只能留到以后见分晓了。

immutable和mutable的Set

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!”):

Scala学习8 – Set和Map

虽然结果差不多,但是还是有些不同的:不可变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)   } 

执行结果:

Scala学习8 – Set和Map

看了下“+”方法的描述,是创建了一个新的对象:

  /** 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

Map和Set类似,采用继承机制和trait提供了两种版本的Map:

Scala学习8 – Set和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的值:

Scala学习8 – Set和Map

不可变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"); 

就这样。

###########

原文  http://www.zhyea.com/2016/04/15/scala-8-set-and-map.html
正文到此结束
Loading...