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)
数组与列表之间的互转
另一方面,如果你需要用集合初始化列表或数组,非常简单,直接做就是了。使用集合初始化列表,只须对集合调用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)
scala编程第17章学习笔记(3)的更多相关文章
- scala编程第17章学习笔记(4)——元组
元组可以把固定数量的条目组合在一起以便于作为整体传送.不像数组或列表,元组可以保存不同类型的对象. 元组常用来返回方法的多个值.例如,下面的方法找到集合中的最长单词并返回它的索引: scala> ...
- scala编程第17章学习笔记(2)——集和映射
默认情况下在使用“Set”或“Map”的时候,获得的都是不可变对象.如果需要的是可变版本,需要先写明引用. 如果同一个源文件中既要用到可变版本,也要用到不可变版本的集合或映射,方法之一是引用包含了可变 ...
- scala编程第17章学习笔记(1)——集合类型
列表 列表的初始化及对其首尾的访问: scala> val colors = List("red", "blue", "green") ...
- scala编程第16章学习笔记(3)——List类的高阶方法
列表间映射:map.flatMap和foreach 1.xs map f 操作返回把函数f应用在xs的每个列表元素之后由此组成的新列表.如: scala> List(1, 2, 3) map ( ...
- scala编程第16章学习笔记(2)
转换列表:toIterator, toArray,copyToArray List类的toArray方法将递归存放的列表转换为连续存放的数组 Array类的toList方法将连续存放的数组转换为递归存 ...
- scala编程第16章学习笔记(1)
List列表的基本操作 head方法获得列表的第一个元素 tail方法获得列表除第一个元素之外的其它元素 isEmpty:判断列表是否为空,空的话返回真 last:获得列表最后一个元素 init:获得 ...
- scala编程第19章学习笔记(1)——类型参数化
一.queues函数式队列 函数式队列是一种具有以下三种操作方式的数据结构: head 返回队列的第一个元素. tail 返回除第一个元素之外的队列. scala> import scala.c ...
- scala编程第18章学习笔记——有状态的对象
银行账号的简化实现: scala> class BankAccount{ | private var bal: Int = 0 | def balance: Int = bal | def de ...
- scala编程第16章学习笔记(4)——List对象的方法
通过元素创建列表:List.apply List(1, 2, 3) 等价于List.apply(1, 2, 3): scala> List.apply(1, 2, 3) res0: List[I ...
随机推荐
- 黑马程序员_java基础笔记(05)...String类
—————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流!—————————— java.lang包 基本信息中 String就是C++.java等编程语言中的字符 ...
- Dubbo中多协议
Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议 1.不同服务不同协议配置 不同服务在性能上适用不同协议进行传输,比如大数据用短连接协议,小数据大并发用长连接协议 & ...
- 005 Ajax中使用jquery实现三种格式的信息
1.jquery中的ajax 二:load 2.load方法 3.load测试程序大纲 4.load测试程序 <!DOCTYPE html> <html> <head&g ...
- 【原创】MySQL CPU %sys高的案例分析(二)
后面又做了补充测试,增加了每秒context switch的监控,以及SQL执行时各步骤消耗时间的监控. [测试现象一] 启用1000个并发线程的压测程序,保持压测程序持续运行,保持innodb_sp ...
- 绝对良心的 Java 中发邮件功能
开篇语,是不是感觉这个功能都老掉牙了,网上一大推的文章,随便找个代码就是了,为什么我还要选择专门写一篇呢,因为我遇到了不一样的坑…… 首先,不免俗套的把代码都贴上来,拿去执行吧,记住换上你的账号和授权 ...
- Android Actionbar Tab 导航模式
Android Actionbar Tab 下图中,红色矩形圈起来的就是我们 ActionBar Tab,下面我们将一步一步的实现下图中的效果. 初次尝试 package com.example.it ...
- 02-c#基础之01-基础语法(一)
1.注释符 1)注销 2) 解释 2.C#中的3种注释符 1)单行注释// 2)多行注释/*要注释的内容*/ 3)文档注释///多用来解释类或者方法 2.VS中的快捷键
- php最简单最基础入门笔记
偶然翻到之前刚学php时记录的笔记,特此分享给大家,希望对初学者有所帮助. php网页命名不支持中文 isset($abc) 判断变量是否被定义 empty($abc) 判断变量是否为空 u ...
- BZOJ3589动态树
**错误改了一上午. 先做熟练泼粪 k<=5,因此我们可以模拟这个过程,在线段树上把标记建出来然后pushup时候更新就好了. By:大奕哥 #include<bits/stdc++.h& ...
- bzoj 1336 最小圆覆盖
最小圆覆盖 问题:给定平面上的一个点集,求半径最小的一个圆,使得点集中的点都在其内部或上面. 随机增量算法: 定义:点集A的最小圆覆盖是Circle(A) 定理:如果Circle(A)=C1,且a不被 ...