Scala學習8 – Set和Map

GuaTompson 8年前發布 | 33K 次閱讀 Scala Scala開發

概述

先來看張圖:

這個很像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中集合的類圖,來看一下:

與上圖比較可以看到有明顯的不同:在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!”):

雖然結果差不多,但是還是有些不同的:不可變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

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");

就這樣。

來自: http://www.zhyea.com/2016/04/15/scala-8-set-and-map.html

 本文由用戶 GuaTompson 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!