Scala Collection

Scala提供了一套很好的集合实现,提供了一些集合类型的抽象。

Scala 集合分为可变的和不可变的集合:

  • 可变集合可以在适当的地方被更新或扩展。这意味着你可以修改,添加,移除一个集合的元素。
  • 不可变集合类,相比之下,永远不会改变。可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变。

常用集合类型:

  • Scala List(列表):List的特征是其元素以线性方式存储,集合中可以存放重复对象。
  • Scala Set(集合):Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。
  • Scala Map(映射):Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。
  • Scala 元组:元组是不同类型的值的集合
  • Scala Option:Option[T] 表示有可能包含值的容器,也可能不包含值。
  • Scala Iterator(迭代器):迭代器不是一个容器,更确切的说是逐一访问容器内元素的方法。

下面将说明这六种集合类型,在jupyter中查看效果更佳哦!传送门~

List 列表

Scala 列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同:列表是不可变的,值一旦被定义了就不能改变,其次列表具有递归的结构(也就是链接表结构)而数组不是。

1
2
3
// 字符串列表
val name: List[String] = List("Shen", "Meng", "Jia")
name
1
2
3
// 整型列表
val nums: List[Int] = List(1, 2, 3, 4)
nums
1
2
// 空列表
val empty: List[Nothing] = List()
1
2
3
4
5
6
7
8
// 二维列表
val dim: List[List[Int]] =
List(
List(1, 0, 0),
List(0, 1, 0),
List(0, 0, 1)
)
dim

PS:构造列表的两个基本单位是 Nil::Nil 也可以表示为一个空列表。上述定义可以重新写为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 字符串列表
val site = "Shen" :: ("Meng" :: ("Jia" :: Nil))
val site_simple= "Shen" :: "Meng":: "Jia"::Nil

// 整型列表
val nums = 1 :: (2 :: (3 :: (4 :: Nil)))
val nums_simple = 1 :: 2 :: 3 :: 4 :: Nil
// 空列表
val empty = Nil

// 二维列表
val dim = (1 :: (0 :: (0 :: Nil))) ::
(0 :: (1 :: (0 :: Nil))) ::
(0 :: (0 :: (1 :: Nil))) :: Nil

PS:对于::操作符的解释:该操作被称为 cons,意为构造,向队列的头部追加数据创造新的列表。用法为 x::list,其中 x 为加入到头部的元素,无论 x是列表与否,它都只将成为新生成列表的第一个元素,length+1。(btw, x::list等价于list.::(x))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
val site1 = "dreamhomes" :: "Google" :: "Baidu" :: Nil
val site2 = "Facebook" :: "Taobao" :: Nil

// 使用 :: 运算符
println("site::site2"+site1::site2)
println("site::site2"+site1.::(site2))
// 使用 ::: 运算符
var fruit = site1 ::: site2
println( "site1 ::: site2 : " + fruit )

// 使用 List.:::() 方法
fruit = site1.:::(site2)
println( "site1.:::(site2) : " + fruit )

// 使用 concat 方法
fruit = List.concat(site1, site2)
println( "List.concat(site1, site2) : " + fruit )
1
2
3
4
5
List(site::site2List(dreamhomes, Google, Baidu), Facebook, Taobao)
site::site2List(List(Facebook, Taobao), dreamhomes, Google, Baidu)
site1 ::: site2 : List(dreamhomes, Google, Baidu, Facebook, Taobao)
site1.:::(site2) : List(Facebook, Taobao, dreamhomes, Google, Baidu)
List.concat(site1, site2) : List(dreamhomes, Google, Baidu, Facebook, Taobao)

列表基本操作

Scala列表有三个基本操作:

  • head 返回列表第一个元素
  • tail 返回一个列表,包含除了第一元素之外的其他元素
  • isEmpty 在列表为空时返回true
1
2
3
4
5
6
7
val name = "Shen"::"Meng"::"JIa"::Nil
val nums = Nil

println( "第一元素是 : " + name.head )
println( "最后元素是 : " + name.tail )
println( "查看列表 site 是否为空 : " + name.isEmpty )
println( "查看 nums 是否为空 : " + nums.isEmpty )
第一元素是 : Shen
最后元素是 : List(Meng, JIa)
查看列表 site 是否为空 : false
查看 nums 是否为空 : true

对于列表操作方法很多,可以参考语法教程:Scala List

Set 集合

Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的。

Scala 集合分为可变的和不可变的集合。

默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。

1
2
3
4
5
6
// 不可变set
val set = Set(1,2,3)
println(set.getClass.getName)

println(set.exists(_ % 2 == 0))
println(set.drop(1))
scala.collection.immutable.Set$Set3
true
Set(2, 3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 可变 set
import scala.collection.mutable.Set // 可以在任何地方引入 可变集合

val mutableSet = Set(1,2,3)
println(mutableSet.getClass.getName) // scala.collection.mutable.HashSet

mutableSet.add(4)
mutableSet.remove(1)
mutableSet += 5
mutableSet -= 2

println(mutableSet)

val another = mutableSet.toSet
println(another.getClass.getName) // scala.collection.immutable.Set
scala.collection.mutable.HashSet
HashSet(3, 4, 5)
scala.collection.immutable.Set$Set3

PS:虽然可变Set和不可变Set都有添加或删除元素的操作,但是有一个非常大的差别。对不可变Set进行操作,会产生一个新的set,原来的set并没有改变,这与List一样。 而对可变Set进行操作,改变的是该Set本身,与ListBuffer类似。

操作方法参考 Scala Sets

Map 映射

Map(映射)是一种可迭代的键值对(key/value)结构。所有的值都可以通过键来获取。Map 中的键都是唯一的。

Map 也叫哈希表(Hash tables),与python中的字典类似。

默认情况下 Scala 使用不可变 Map。如果你需要使用可变集合,你需要显式的引入 import scala.collection.mutable.Map 类。在 Scala 中 你可以同时使用可变与不可变 Map,不可变的直接使用 Map,可变的使用 mutable.Map

1
2
3
4
5
// 空哈希表,键为字符串,值为整型
var A:Map[Char,Int] = Map()

// Map 键值对演示
val colors = Map("red" -> "#FF0000", "azure" -> "#F0FFFF")
1
2
3
4
//定义 Map 时,需要为键值对定义类型。如果需要添加 key-value 对,可以使用 + 号
A += ('I' -> 1)
A += ('J' -> 5)
A
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Map 访问
val colors = Map("red" -> "#FF0000",
"azure" -> "#F0FFFF",
"peru" -> "#CD853F")

val nums: Map[Int, Int] = Map()

println( "colors 中的键为 : " + colors.keys )
println( "colors 中的值为 : " + colors.values )
println( "检测 colors 是否为空 : " + colors.isEmpty )
println( "检测 nums 是否为空 : " + nums.isEmpty )

println("检测是否包含键值red:" + colors.contains("red"))

println("输出键值对:")
colors.keys.foreach{ i =>
print( "Key = " + i )
println(" Value = " + colors(i))}
colors 中的键为 : Set(red, azure, peru)
colors 中的值为 : Iterable(#FF0000, #F0FFFF, #CD853F)
检测 colors 是否为空 : false
检测 nums 是否为空 : true
检测是否包含键值red:true
输出键值对:
Key = red Value = #FF0000
Key = azure Value = #F0FFFF
Key = peru Value = #CD853F

PS:=>表示匿名函数,(形参列表) => {函数体},例如:(x:Int) => x +1 等同于 lambda x:x+1

其它操作方法参考:Scala Map

Tuple 元组

与列表一样,元组也是不可变的,但与列表不同的是元组可以包含不同类型的元素。

元组的值是通过将单个的值包含在圆括号中构成的。

1
2
3
4
5
6
7
8
val t = (1, 3.14, "Fred")
//val t1 = new Tuple3(1, 3.14, "Fred")

//访问元组中的元素
println(t._1 + t._2)

// 迭代输出
t.productIterator.foreach{ i =>println("Value = " + i )}
4.140000000000001
Value = 1
Value = 3.14
Value = Fred

更多操作参考:Scala Tuple3

Option 选项

Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。

Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None

Option 有两个子类别,一个是 Some,一个是 None,当他回传 Some 的时候,代表这个函式成功地给了你一个 String,而你可以透过 get() 这个函式拿到那个 String,如果他返回的是 None,则代表没有字符串可以给你。

1
2
3
4
5
6
val myMap: Map[String, String] = Map("key1" -> "value")
val value1: Option[String] = myMap.get("key1")
val value2: Option[String] = myMap.get("key2")

value1
value2
1
2
3
4
5
6
7
// 可以通过模式匹配来输出匹配值
def show(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
show(value1)
show(value2)

更多操作方法参考:Scala Option

Iterator 迭代器

Scala Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。

迭代器 it 的两个基本操作是 next 和 hasNext:

  • 调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。
  • 调用 it.hasNext() 用于检测集合中是否还有元素。

让迭代器 it 逐个返回所有元素最简单的方法是使用 while 循环。

1
2
3
4
5
val it = Iterator("Baidu", "Google", "Dreamhomes", "Taobao")

while (it.hasNext){
println(it.next())
}
Baidu
Google
Dreamhomes
Taobao

更多方法参考:Scala Iterator

联系作者