3 数据结构
3.1 容器(Collection)
Scala提供了一套丰富的容器(Collection)包括List、Array、Set和Map等;容器可以分为有序和无序,可变和不可变等不同容器类别。
Scala用了三个包来组织容器,分别是scala.collection、scala.collection.mutable(可变容器)和scala.collection.immutable(不可变容器)
3.2 列表(List)
列表是一种共享相同类型的不可变的对象序列。是不可变的集合,并将其定义在scala.collection.immutable包中。
不同于Java的java.util.List,scala的List一旦被定义其值就不能改变,因此声明List时必须被初始化。
var strList = List("BigData", "Hadoop", "Spark")
// 若要使用可变List,则如下
import scala.collection.mutable.ListBuffer
var strList = ListBuffer("hadoop","spark","scala")
var strList += "BUAA"
println(strList)
- 列表有头部和尾部的概念,可以分别使用 head 和 tail 方法来获取。
- head 返回的是列表的第一个元素的值,tail 返回的是除第一个元素外的其他值构成的新列表。
- strList.head 将返回字符串“BigData”,strList.tail 返回 List("Hadoop","Spark")
构造列表常用的方法是通过在已有列表前端增加元素,使用的操作符号为::,例如:
var otherList = "Apache"::strList
scala> List(Apache,BigData,Hadoop,Spark)
而在列表的后端增加元素,使用方法 appended() ,若要合并两个List,则使用appendedAll(),比如:
val strList = List("Hadoop","Spark")
val strElement = "Scala"
val add_elem = strList.appended(strElement) // 在List后面添加元素
val add_list = strElement.appendedAll(strList) // 整合两个List内容,合为一个List
// 若对增加的List使用appended方法,则出现在新List中嵌套增加的原List,没有整合成一个List
3.3 集合(Set)
Set是不重复元素的容器(Collection)。List 中的元素师按照插入的先后顺序来组织的,但Set 中的元素并不会记录元素的插入顺序,而是会以Hash的方式对元素值进行组织,所以,Set允许快速地找到某个元素。
Set包括可变集和不可变集,分别位于scala.collection.mutable包和scala.collection.immutable包,在缺省情况下创建的是不可变集。
var mySet = Set("Hadoop","Spark")
mySet += "Scala"
如果要声明一个可变集,则需要提前引入scala.collection.mutable.Set
import scala.collection.mutable.Set
val myMutableSet = Set("Database","BigData")
myMutabelSet += "Cloud Computing"
3.4 映射(Map)
Map是一系列键值对的容器,在一个映射中,键是唯一的但值不一定是唯一的,可以根据键来对值进行快速检索。
和集合一样,scala采用了类继承机制,提供了可变的和不可变的两种版本映射,分别定义在包scala.collection.mutable和scala.collection.immutable里面,默认情况下使用的是不可变的映射,若想使用可变映射,必须明确的导入scala.collection.mutable.Map
val university = Map("XMU"->"Xiamen University", "THU"->"Tsinghua University", "PKU"->"Peking University")
更新已有元素和添加元素;或使用+=来添加新元素
import scala.collection.mutable.Map
val university2 = Map("XMU"->"Xiamen University", "THU"->"Tsinghua University")
university2("XMU") = "Ximan University" // 更新已有元素的值
university2("FZU") = "FuZhou University" // 添加新元素
// 也可以使用+=操作来添加新的元素
university2 += ("TJU"->"Tianjin University")
ubiversity2 += ("SDU"->"Shandong University","WHU"->"Wuhan University")
- 循环遍历映射Map(也可以设置守卫)
for ((k,v) <- 映射) 语句块
for ((k,v) <- university) printf("Code is : %s and name is %s\n",k,v)
// 或者也可以只遍历映射中的k或者v
for (k <- university.keys) println(k)
for (v <- university.values) println(v)
// 在遍历的过程中同样可以设置“守卫”,比如:
for ((k,v)<-university if k == "THU"){
println(k,v)
}
3.5 迭代器(Iterator)
在Scala中,迭代器(Iterator)不是一个集合,但是,提供了访问集合的一种方法。
迭代器包含两个基本操作:next和hasNext。next可以返回迭代器的下一个元素hasNext用于检测是否还有下一个元素。
val iter = Iterator("Hadoop","Spark","Scala")
while (iter.hasNext){
println(iter.next())
}
val iter = Iterator("Hadoop","Spark","Scala")
for (elem <- iter){
println(elem)
}
Iterable有两个方法返回迭代器:grouped和sliding。这些迭代器返回的不是单个元素,而是原容器(Collection)元素的全部子序列。这些最大的子序列作为参数传给这些方法。
其中grouped方法返回元素的增量分块,sliding方法生成一个滑动元素的窗口。(为截取固定部分数据或者固定大小的滑动窗口数据提供了方便)
3.6 数组(Array)
数组是一种可变的、可索引的、元素具有相同类型的数据集合,它是各种高级语言中最常用的数据结构。Scala提供了参数化类型的通用数组类Array[T],其中T可以是任意的Scala类型,可以通过显式指定类型或者通过隐式推断来实例化一个数组。
val intValueArr = new Array[int](3)
intValueArr(0) = 12
intValueArr(1) = 45
intValueArr(2) = 33
val strValueArr = new Array[string](3)
strValueArr(0) = "BigData"
strValueArr(1) = "Hadoop"
strValueArr(2) = "Spark"
for (i <- 0 to 2){println(strValueArr(i))}
- 定义二维数组和三维数组,可以使用多级圆括号来访问多维数组的元素,例如:myMatrix(0)(1)返回第一行第二列元素。
val myMatrix = Array.ofDim[Int](3,4) // 实际类型是Array[Array[Int]]
val myCode = Array.ofDim[String](3,2,4) // 实际类型是Array[Array[Array[Int]]]
- 采用Array类型定义的数组属于定长数组,其数组长度在初始化后就不能改变。如果要定义变长数组,需要使用ArrayBuffer参数类型,其位于包scala.collection.mutable中,举例如下。
import scala.collection.mutable.ArrayBuffer
val aMutableArr = ArrayBuffer(10,20,30)
aMutableArr += 40 // 如果是定义Array则不能够直接使用+=
aMutableArr.insert(2,60)
aMutableArr -= 40
var temp = aMutableArr.remove(2)
3.7 元组(Tuple)
元组是不同类型的值的聚集。元组和列表不同,列表中各个元素必须是相同类型,而元组可以包含不同类型的元素。
val tuple = ("BigData", 2015, 45.0)
println(tuple._1)
println(tuple._N) // N代表具体位置的元素,从1开始,用._N表示,import时._表示导入所有的包