可變(mutable)集合與不可變(immutable)集合數組
爲了更易於完成不可變集合到可變集合的轉換,或者反向轉換,Scala提供了一些語法糖。縱使不可變集和映射並不支持真正的+=方法,Scala仍是爲此提供了+=的語法解釋。app
scala> val people = Set("Nancy", "Jane") people: scala.collection.immutable.Set[String] = Set(Nancy, Jane) scala> people += "Bob" <console>:9: error: value += is not a member of scala.collection.immutable.Set[S tring] people += "Bob" ^
然而若是people聲明爲var,而不是val,那麼集合就能夠用+=操做完成「更新」,儘管它是不可變類型的。首先,新建立集合;而後,people將被從新賦值爲新集合:ui
scala> var people = Set("Nancy", "Jane") people: scala.collection.immutable.Set[String] = Set(Nancy, Jane) scala> people += "Bob" scala> people res2: scala.collection.immutable.Set[String] = Set(Nancy, Jane, Bob)
一樣的理念能夠應用於全部以=結尾的方法,而不只是+=方法。如下代碼把該語法應用於-=操做符,從集中移除元素;以及++=操做符,把集合的全部元素添加到集裏面:es5
scala> people -= "Jane" scala> people ++= List("Tom", "Harry") scala> people res5: scala.collection.immutable.Set[String] = Set(Nancy, Bob, Tom, Harry)
這塊語法糖不只對集合有效,它還具備普適性。例如,下面是用在浮點數上的:spa
scala> var roughlyPi = 3.0 roughlyPi: Double = 3.0 scala> roughlyPi += 0.1 scala> roughlyPi += 0.04 scala> roughlyPi res8: Double = 3.14
這種擴展的效果相似於Java的賦值操做符+=、-=、*=等,不過其更爲通用,由於全部以=結尾的操做符均可以作轉化。scala
初始化集合code
最多見的建立和初始化集合的方法是把初始值傳遞給要用的集合類型的伴生對象的工廠方法。你只須把元素放在伴生對象名後面的括號中,Scala編譯器就會把它轉化爲該伴生對象的apply方法調用:對象
scala> List(1, 2, 3) res9: List[Int] = List(1, 2, 3) scala> Set('a', 'b', 'c') res10: scala.collection.immutable.Set[Char] = Set(a, b, c) scala> import scala.collection.mutable import scala.collection.mutable scala> mutable.Map("hi" -> 2, "there" -> 5) res11: scala.collection.mutable.Map[String,Int] = Map(hi -> 2, there -> 5) scala> Array(1.0, 2.0, 3.0) res12: Array[Double] = Array(1.0, 2.0, 3.0)
儘管一般均可以讓Scala的編譯器從傳遞給工廠方法的元素推斷集合的元素類型,但有些時候或許你會但願指定以不一樣於編譯器所選的類型建立集合。尤爲對於可變集合來講更是如此。舉例以下:blog
scala> import scala.collection.mutable import scala.collection.mutable scala> val stuff = mutable.Set(42) stuff: scala.collection.mutable.Set[Int] = Set(42) scala> stuff += "abracadabra" <console>:11: error: type mismatch; found : String("abracadabra") required: Int stuff += "abracadabra" ^
這裏的問題在於stuff被指定的類型爲Int。若是想要讓它的類型爲Any,你須要明確地說明,把元素類型放在方括號裏,以下:ci
scala> val stuff = mutable.Set[Any](42)
stuff: scala.collection.mutable.Set[Any] = Set(42) scala> stuff += "abracadabra" res14: stuff.type = Set(abracadabra, 42)
另外一種特殊狀況是,你想要把集合初始化爲指定類型。例如,設想你要把列表中的元素保存在TreeSet中。列表以下:
scala> val colors = List("blue", "yellow", "red", "green")
colors: List[String] = List(blue, yellow, red, green)
你不能把colors列表傳遞給TreeSet工廠方法:
scala> import scala.collection.immutable.TreeSet import scala.collection.immutable.TreeSet scala> val treeSet = TreeSet(colors) <console>:11: error: No implicit Ordering defined for List[String]. val treeSet = TreeSet(colors) ^
實際上,須要建立空的TreeSet[String]對象並使用TreeSet的++操做符把列表元素加入其中:
scala> val treeSet = TreeSet[String]() ++ colors
treeSet: scala.collection.immutable.TreeSet[String] = TreeSet(blue, green, red,yellow)
數組與列表之間的互轉
另外一方面,若是你須要用集合初始化列表或數組,很是簡單,直接作就是了。使用集合初始化列表,只須對集合調用toList方法:
scala> treeSet.toList
res0: List[String] = List(blue, green, red, yellow)
或者,若是須要的是數組,則調用toArray:
scala> treeSet.toArray
res1: Array[String] = Array(blue, green, red, yellow)
請牢記,轉變爲列表或數組一樣須要複製集合的全部元素,所以對於大型集合來講可能比較慢。
集合映射的可變與不可變互轉
另外一種偶爾發生的狀況是把可變集或映射轉換成不可變類型,或者反向轉換。要作到這一點,你能夠利用前面以列表元素初始化TreeSet時的演示技巧。好比說你想要把當前使用的可變集合轉換成不可變集合,能夠先建立空的不可變集合,而後把可變集合的元素用++操做符添加進去。下面的代碼說明了如何把前面例子裏的不可變TreeSet轉換爲可變集,再轉回不可變集:
scala> import scala.collection.mutable import scala.collection.mutable scala> treeSet res2: scala.collection.immutable.TreeSet[String] = TreeSet(blue, green, red, yel low) scala> val mutaSet = mutable.Set.empty ++ treeSet mutaSet: scala.collection.mutable.Set[String] = Set(red, blue, green, yellow) scala> val immutaSet = Set.empty ++ mutaSet immutaSet: scala.collection.immutable.Set[String] = Set(red, blue, green, yellow )
可使用一樣的技巧實現可變映射與不可變映射之間的轉換:
scala> val muta = mutable.Map("i" -> 1, "ii" -> 2) muta: scala.collection.mutable.Map[String,Int] = Map(ii -> 2, i -> 1) scala> val immu = Map.empty ++ muta immu: scala.collection.immutable.Map[String,Int] = Map(ii -> 2, i -> 1)