Programming In Scala笔记-第十七章、Scala中的集合类型
本章主要介绍Scala中的集合类型,主要包括:Array, ListBuffer, Arraybuffer, Set, Map和Tuple。
一、序列
序列类型的对象中包含多个按顺序排列好的元素,可以访问其中特定位置的元素。序列类型主要包括List,Array, ListBuffer, ArrayBuffer 。
1、List
List在前一章已经介绍过,略。
2、Array
数组在很多编程语言中都会用到。下面代码中包括了如何定义一个Array类型变量,如何在定义Array变量时赋初始值,以及如何访问和更新特定位置的元素。
val fiveInts = new Array[Int](5) // 生成一个长度为5的数组
val fiveToOne = Array(5, 4, 3, 2, 1) // 生成一个长度为5的数组并初始化
fiveInts(0) = fiveToOne(4) // 访问指定位置上的元素并赋值
fiveInts
运行结果如下,
Scala中的数组和Java中的数组是相同的。
3、ListBuffer
ListBuffer类型的完整路径名为scala.collection.mutable.ListBuffer。
在ListBuffer对象的前面和后面增加新元素都非常的方便,使用+=方法在该对象后新增元素,使用+=:在该对象前新增元素。当元素添加完毕后,调
用toList方法将ListBuffer对象转化成List,使得构建List对象更加高效。
import scala.collection.mutable.ListBuffer
val buf = new ListBuffer[Int]
buf += 1
buf += 2
buf
3 +=: buf
buf.toList
结果如下,
4、ArrayBuffer
ArrayBuffer的完整路径是scala.collection.mutable.ArrayBuffer。ArrayBuffer和Array类似,支持所有Array上的操作。
使用ArrayBuffer的好处是,定义时可以不指定长度。并且在ArrayBuffer的头部和尾部添加或移除元素更加便捷。
import scala.collection.mutable.ArrayBuffer
val buf = new ArrayBuffer[Int]()
buf += 12
buf += 15
buf
buf.length
buf(0)
运行结果如下,
5、String
String对象本质上是字符序列。可以直接在String对象上进行遍历,遍历的内容就是该对象的每一个字符元素。
val a = "abcdefg"
a.foreach(println)
def hasUpperCase(s: String) = s.exists(_.isUpper)
hasUpperCase("Robert Frost")
hasUpperCase("e e cummings")
运行结果如下,
二、Set和Map
Scala中同时提供了mutable和immutable类型的Set和Map类型。有关Set和Map类型的类继承关系,如下图所示,
Map类继承关系:
Set类继承关系:
从上面两图可以看到,分别有三个Map和Set命名的trait,只不过这三个trait位于不同的package中。直接使用Map或者Set,在默认情况下,使用的是imutable这个。如果想要实现mutable类型的Set或Map需要显式的import。
下面分别介绍Set和Map类型。
1、Set
Set对象中不会包含重复元素。下面将一个String类型变量切割成单词,然后生成一个Set对象。
val text = "See Spot run. Run, Spot. Run!"
val wordsArray = text.split("[ !,.]+")
val words = mutable.Set.empty[String]
for (word <- wordsArray)
words += word.toLowerCase
words
运行结果如下,最终的Set对象中只包含了三个不重复的元素。
Set对象上的常用操作列表如下,注意区分哪些是mutable类型的Set,哪些是imutable类型的Set。
| 操作符 | 作用及结果 |
|---|---|
val nums = Set(1, 2, 3) |
生成一个新的Set对象,并初始化 |
nums + 5 |
新增一个元素,得到一个新的Set对象,结果为Set(1, 2, 3, 5) |
nums - 3 |
删除Set中的一个元素,结果为Set(1, 2, 5) |
nums ++ List(5, 6) |
将List中的元素全部增加到Set中,结果为Set(1, 2, 3, 5, 6) |
nums -- List(1, 2) |
去除Set中的包含在List中的元素,结果为Set(3) |
nums $ Set(1, 3, 5, 7) |
返回两个Set对象中共有的元素,结果为Set(1, 3) |
nums.size |
获取当前Set中的元素个数,结果为3 |
nums.contains(3) |
判断nums中是否包含指定元素,结果为true |
import scala.collection.mutable |
引入mutable类型的Set对象 |
val words = mutable.Set.empty[String] |
生成一个空的mutable.Set对象 |
words += "the" |
往words中增加元素,words的内容随之发生变化,结果为Set(the) |
words -= "the" |
从words中移除元素,此时words为空,结果为Set() |
words ++= List("do", "re", "mi") |
将List中的元素全部添加到words中,结果为Set(do, re, mi) |
words --= List("do", "re") |
将List中包含的元素从words中移除,结果为Set(mi) |
words.clear |
清空words,移除全部元素,结果为Set() |
2、Map
直接看示例,展示了如何新建Map对象,如何往Map对象中添加键值对,以及如何从Map对象中获取指定key的value值。
val map = mutable.Map.empty[String, Int]
map("hello") = 1
map("there") = 2
map
map("hello")
运行结果为,
Map上的常见操作如下,注意区分哪些是mutable类型的Map对象,哪些是imutable类型的Map对象。
| 操作符 | 作用及结果 |
|---|---|
val nums = Map("i" -> 1, "ii" -> 2) |
生成一个新的Map对象,并初始化 |
nums + ("vi" -> 6) |
新增一个元素,得到一个新的Map对象,结果为Map(i -> 1, ii -> 2, vi -> 6) |
nums - "ii" |
删除Map中的一个元素,结果为Map(i -> 1) |
nums ++ List("iii" -> 3, "v" -> 5) |
将List中的元素全部增加到Map中,结果为Map(i -> 1, ii -> 2, iii -> 3, v -> 5) |
nums -- List("i", "ii") |
去除Map中的key为包含在List中的元素,结果为Map() |
nums.size |
获取当前Map中的键值对个数,结果为2 |
nums.contains("ii") |
判断nums中是否包含指定key为ii的键值对,结果为true |
nums("ii") |
获取指定key的value值,结果为2 |
nums.keys |
获取当前nums对象中所有的key值 |
nums.keySet |
获取当前nums对象中所有的key值 ,以Set形式返回。结果为Set(i, ii) |
nums.values |
获取当前nums对象中所有的value值 |
nums.isEmpty |
判断nums是否为空,结果为false |
import scala.collection.mutable |
引入mutable类型的Map对象 |
val words = mutable.Map.empty[String, Int] |
生成一个空的mutable.Map对象 |
words += ("one" -> 1) |
往words中增加元素,words的内容随之发生变化,结果为Map(one -> 1) |
words -= "one" |
从words中移除元素,此时words为空,结果为Map() |
words ++= List("one" -> 1, "two" -> 2, "three" -> 3) |
将List中的键值对全部添加到words中,结果为Map(one -> 1, two -> 2, three -> 3) |
words --= List("one", "two") |
将List中包含的key从words中移除,结果为Map(three -> 3) |
3、TreeMap和TreeSet的其他子类
Map和Set还有其他形式的子类,比如TreeSet,TreeMap。
前面展示的Map和Set中的元素都是无序的,需要有序的Map和Set可以使用TreeMap和TreeSet类型。TreeSet是对其中的元素进行排序,TreeMap是对其中键值对的Key进行排序,底层使用的是红黑树。
import scala.collection.immutable.TreeSet
val ts = TreeSet(9, 3, 1, 8, 0, 2, 7, 4, 6, 5)
val cs = TreeSet('f', 'u', 'n')
import scala.collection.immutable.TreeMap
var tm = TreeMap(3 -> 'x', 1 -> 'x', 4 -> 'x')
tm += (2 -> 'x')
tm
运行结果如下,
三、初始化集合
在前面的示例代码中可以看到,一般是调用该类型伴生对象的工厂方法,并且传入初始参数值来初始化一个集合的对象。比如
List(1, 2, 3)
Set('a', 'b', 'c')
import scala.collection.mutable
mutable.Map("hi" -> 2, "three" -> 5)
Array(1.0, 2.0, 3.0)
运行结果如下,从结果可以看到,Scala编译器会根据传入初始参数的类型,推断出集合中的元素类型。
但是,对于mutable类型的集合对象来说,由于需要动态的增加新元素,最好在初始化集合对象时手动声明其类型,否则会出现以下报错情况。
val stuff = mutable.Set(42)
stuff += "abracadabra"
报错如下,由于初始化时传入的是Int类型元素,Scala编译器会认为该Set对象中的元素必须是Int类型,当新增一个String类型元素时,就会报出类型不匹配的错。
正确的做法如下,
val stuff: mutable.Set[Any] = mutable.Set(42)
stuff += "abracadabra"
结果如下,
四、元组
Scala中提供一种特殊的类型,Tuple。Tuple中可以存储不同类型的元素,元组元素用圆括号包围。如下所示
val t = (1, "hello", Console)
访问Tuple中的元素,使用_1表示第一个元素,_2表示第二个元素,以此类推。比如
t._1
t._2
t._3
运行结果如下,
也可以在生成Tuple对象时直接指定各元素对应的变量名,相当于同时声明并初始化多个元素。需要注意的是变量个数与元组中元素个数需要保持一致。
val (t1, t2, t3) = (1, "hello", Console)
结果如下,
Programming In Scala笔记-第十七章、Scala中的集合类型的更多相关文章
- Programming In Scala笔记-第十一章、Scala中的类继承关系
本章主要从整体层面了解Scala中的类层级关系. 一.Scala的类层级 在Java中Object类是所有类的最终父类,其他所有类都直接或间接的继承了Object类.在Scala中所有类的最终父类为A ...
- Programming In Scala笔记-第五章、Scala中的变量类型和操作
这一章的一些基础性的东西,主要包括Scala中的基本变量类型,以及相关的一些操作符. 一.简单类型 下表中列出Scala语言中的基本类型,以及其字节长度,其中Byte, Short, Int, Lon ...
- Programming In Scala笔记-第七章、Scala中的控制结构
所谓的内建控制结构是指编程语言中可以使用的一些代码控制语法,如Scala中的if, while, for, try, match, 以及函数调用等.需要注意的是,Scala几乎所有的内建控制结构都会返 ...
- [汇编学习笔记][第十七章使用BIOS进行键盘输入和磁盘读写
第十七章 使用BIOS进行键盘输入和磁盘读写 17.1 int 9 中断例程对键盘输入的处理 17.2 int 16 读取键盘缓存区 mov ah,0 int 16h 结果:(ah)=扫描码,(al) ...
- C++ primer plus读书笔记——第14章 C++中的代码重用
第14章 C++中的代码重用 1. 使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现).获得接口是is-a关系的组成部分.而使用组合,类可以获得实现,但不能获得接口. ...
- Programming In Scala笔记-第六章、函数式对象
这一章主要是以定义和完善一个有理数类Rational为线索,分析和介绍有关类定义,构造函数,方法重写,变量定义和私有化,以及对操作符的定义等. 一.Rational类定义和构造函数 1.定义一个空类 ...
- Programming In Scala笔记-第四章、类和对象
类似于Java,Scala中也有类和对象的概念. 一.类.属性和方法 1.类 类是对一类事物的抽象,当一个类被定义后,就可以以该定义为模板,定义该类的一系列对象.比如说有以下一个模板 人类: 有姓名: ...
- 《linux内核设计与实现》读书笔记第十七章
第17章 设备与模块 四种内核成分 设备类型:在所有 Unix 系统中为了统一普通设备的操作所采用的分类. 模块: Linux 内核中用于按需加载和卸载目标码的机制. 内核对象:内核数据结构中支持面向 ...
- The C++ Programming Language 学习笔记 第6章 表达式和语句
1.关于strcpy函数. 书中说c风格的字符串尽量少用,strcpy这样的函数应该也要少用.这里讲这个函数主要是要通过本章课后练习第十题来讲一下前面提及的要点.巩固一下前几章的知识.写了一段,本来感 ...
随机推荐
- 实验吧_密码忘记了(vim编辑器+代码审计)&天网管理系统(php弱比较+反序列化)
密码忘记了 一开始尝试了各种注入发现都无效,在网页源码中找到了admin 的地址,输入地址栏发现并没有什么有用的信息,随便输个邮箱,网页返回了一个地址 ./step2.php?email=youmai ...
- [Codeforces 922E]Birds
Description 题库链接 一条直线上有 \(n\) 棵树,每棵树上有 \(c_i\) 只鸟,在一棵树底下召唤一只鸟的魔法代价是 \(cost_i\) 每召唤一只鸟,魔法上限会增加 \(B\) ...
- [SCOI2010]幸运数字
题目描述 在中国,很多人都把6和8视为是幸运数字!lxhgww也这样认为,于是他定义自己的“幸运号码”是十进制表示中只包含数字6和8的那些号码,比如68,666,888都是“幸运号码”!但是这种“幸运 ...
- 绝世好题bzoj4300
Description 给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=len). Input 输入文件共2行. 第一行包括一个整数 ...
- [USACO13OPEN]重力异常
题目描述 船长正在拯救她的船员,Beefalo 博士. 和所有伟大的冒险故事一样,这个故事也是发生在一个2D平面上的.囧 这个平面是M*N的格子组成的网格,代表着船长的世界的一个侧视图. 有些格子是空 ...
- 洛谷P3275 [SCOI2011]糖果
差分约束大坑题 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring ...
- 【BZOJ3506】【Cqoi2014】排序机械臂
传送门(因为BZOJ上没有题面...所以放的是luogu的) 题意:你需要维护一个序列,支持区间翻转与查询区间最小. 解题思路:由于区间最小实际上每一次就是对应的整个数列的第k小,因此可以直接预处理解 ...
- 【NOIP2013】传染病控制
题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染病,难以准确判别病毒携带 ...
- ●BZOJ 2251 [2010Beijing Wc]外星联络
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2251 题解: 后缀数组,倍增,RMQ 题意:把重复次数超过 1次的子串按字典序输出它们重复的 ...
- python中常见错误及try-except 的用法
1.常见的错误 我们在使用python过程中会出现: (1)SyntaxError 句法错误. (2)IndentationError 缩进错误. (3)NameError 变量未定义错误. (4)T ...