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

可变(mutable)集合与不可变(immutable)集合

为了更易于完成不可变集合到可变集合的转换,或者反向转换,Scala提供了一些语法糖。纵使不可变集和映射并不支持真正的+=方法,Scala还是为此提供了+=的语法解释。

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将被重新赋值为新集合:

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)

同样的理念可以应用于所有以=结尾的方法,而不仅是+=方法。以下代码把该语法应用于-=操作符,从集中移除元素;以及++=操作符,把集合的所有元素添加到集里面:

scala> people -= "Jane"

scala> people ++= List("Tom", "Harry")

scala> people
res5: scala.collection.immutable.Set[String] = Set(Nancy, Bob, Tom, Harry)

这块语法糖不仅对集合有效,它还具有普适性。例如,下面是用在浮点数上的:

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编译器就会把它转化为该伴生对象的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的编译器从传递给工厂方法的元素推断集合的元素类型,但有些时候或许你会希望指定以不同于编译器所选的类型创建集合。尤其对于可变集合来说更是如此。举例如下:

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,你需要明确地说明,把元素类型放在方括号里,如下:

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)
时间: 2024-11-04 00:55:15

scala编程第17章学习笔记(3)的相关文章

scala编程第17章学习笔记(1)——集合类型

列表 列表的初始化及对其首尾的访问: scala> val colors = List("red", "blue", "green") colors: List[String] = List(red, blue, green) scala> colors.head res15: String = red scala> colors.tail res16: List[String] = List(blue, green) 数组 创

scala编程第17章学习笔记(4)——元组

元组可以把固定数量的条目组合在一起以便于作为整体传送.不像数组或列表,元组可以保存不同类型的对象. 元组常用来返回方法的多个值.例如,下面的方法找到集合中的最长单词并返回它的索引: scala> def longestWord(words: Array[String]) = { | var word = words(0) | var idx = 0 | for (i <- 1 until words.length) | if (words(i).length > word.length)

scala编程第17章学习笔记(2)——集和映射

默认情况下在使用“Set”或“Map”的时候,获得的都是不可变对象.如果需要的是可变版本,需要先写明引用. 如果同一个源文件中既要用到可变版本,也要用到不可变版本的集合或映射,方法之一是引用包含了可变版本的包名: scala> import scala.collection.mutable import scala.collection.mutable 与以往一样, 不可变集可以用Set指代,但现在还可以用mutable.Set指代可变集.举例如下: scala> val mutaSet =

scala编程第18章学习笔记——有状态的对象

银行账号的简化实现: scala> class BankAccount{ | private var bal: Int = 0 | def balance: Int = bal | def deposit(amount: Int) { | require(amount > 0) | bal += amount | } | | def withdraw(amount: Int): Boolean = | if (amount > bal) false | else{ | bal -= am

scala编程第16章学习笔记(4)——List对象的方法

通过元素创建列表:List.apply List(1, 2, 3) 等价于List.apply(1, 2, 3): scala> List.apply(1, 2, 3) res0: List[Int] = List(1, 2, 3) 创建数值范围:List.range List.range(from, until),可以创建从from开始到until减一的所有数值的列表.注:尾部until不在范围之内. 还有一个版本的range可以带step值作为第三参数.这个操作可以产生从from开始的,间隔

scala编程第19章学习笔记(1)——类型参数化

一.queues函数式队列 函数式队列是一种具有以下三种操作方式的数据结构: head 返回队列的第一个元素. tail 返回除第一个元素之外的队列. scala> import scala.collection.immutable.Queue import scala.collection.immutable.Queue scala> val q = Queue(1, 2, 3) q: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3

scala编程第16章学习笔记(3)——List类的高阶方法

列表间映射:map.flatMap和foreach 1.xs map f 操作返回把函数f应用在xs的每个列表元素之后由此组成的新列表.如: scala> List(1, 2, 3) map (_ + 1) res0: List[Int] = List(2, 3, 4) scala> val words = List("the", "quick", "brown", "fox") words: List[Strin

scala编程第16章学习笔记(2)

转换列表:toIterator, toArray,copyToArray List类的toArray方法将递归存放的列表转换为连续存放的数组 Array类的toList方法将连续存放的数组转换为递归存放的列表 scala> val arr = abcde.toArray arr: Array[Char] = Array(a, b, c, d, e) scala> arr.toList res24: List[Char] = List(a, b, c, d, e) copyToArray方法可以

scala编程第16章学习笔记(1)

List列表的基本操作 head方法获得列表的第一个元素 tail方法获得列表除第一个元素之外的其它元素 isEmpty:判断列表是否为空,空的话返回真 last:获得列表最后一个元素 init:获得除最后一个元素之外的元素 reverse:反转列表 前缀与后缀:drop.take.splitAt xs take n 返回xs列表的前n个元素,如果n大于xs.length,则返回整个xs. xs drop n 返回xs列表除前n个元素之外的所有元素,如果n大于xs.length,则返回空列表.