scala编程第17章学习笔记(3)

可变(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)
相关文章
相关标签/搜索