Scala 集合框架

概述

Scala 集合框架提供了多种集合类型,包括:

  • 列表(List):不可变链表,支持快速在头部进行插入和删除操作,但不提供快速按下标进行访问。
  • 数组(Array):支持快速按索引进行访问,但插入和删除操作会涉及数组的扩容和移动操作,效率较低。
  • 列表缓冲(ListBuffer):ListBuffer 是一个可变的链表,可以在列表尾部高效地追加元素时,在构建完列表缓冲之后,可以使用 toList 方法将其转换为不可变列表。
  • 数组缓冲(ArrayBuffer):数组缓冲与数组类似。
  • 元组(Tuple):元组是一种不可变的数据结构,可以通过索引访问其中的元素,但无法修改元组中的元素。

Scala 集合类库同时提供了可变和不可变两个版本的集合和映射。当我们使用 SetMap 时,默认得到的是一个不可变的对象,如果想使用可变版本,则需要显式进行引入。

列表基本操作

创建列表

所有的列表都构建自两个基础的构建单元 Nil::(读作“cons”),Nil 用于表示空列表,中缀操作符 :: 用于在列表前追加元素。

1val fruit = "apples" :: ("oranges" :: ("pears" :: Nil))
2val nums = 1 :: (2 :: (3 :: (4 :: Nil)))
3
4println(fruit) // List(apples, oranges, pears)
5println(nums) // List(1, 2, 3, 4)

由于操作符::: 结尾,所以它是右结合的,因此我们可以省略定义中的圆括号,例如:

1val nums = 1 :: 2 :: 3 :: 4 :: Nil
2
3println(nums) // List(1, 2, 3, 4)
1val nums = 1 :: 2 :: 3 :: 4 :: Nil
2
3// 判断列表是否为空
4println(nums.isEmpty) // false
5
6// 获取列表的长度
7println(nums.length) // 4

列表元素选择

 1val nums = 1 :: 2 :: 3 :: 4 :: Nil
 2
 3// 打印列表中的第一个元素
 4println(nums.head) // 1
 5
 6// 打印列表中的最后一个元素
 7println(nums.last) // 4
 8
 9// 打印列表中除第一个元素之外的所有元素构成的列表
10println(nums.tail) // List(2, 3, 4)
11
12// 打印列表中除最后一个元素之外的所有元素构成的列表
13println(nums.init) // List(1, 2, 3)

apply(n: Int) 方法表示获取列表中索引为 n 的元素。

1val nums = 1 :: 2 :: 3 :: 4 :: Nil
2println(nums(1)) // 2
3println(nums.apply(2)) // 3

drop 方法和 take 方法分别是对 head 方法和 tail 方法的一般化:

  • 表达式 list.drop(n) 表示从 list 中删除前 n 个元素,如果 n 大于 list.length,则返回一个空列表。
  • 表达式 list.take(n) 表示从 list 中取出前 n 个元素,如果 n 大于 list.length,则返回 list 本身。
1val nums = 1 :: 2 :: 3 :: 4 :: Nil
2println(nums.drop(2)) // List(3, 4)
3println(nums.take(2)) // List(1, 2)

获取列表中元素的索引构成的列表:

 1val nums = 1 :: 2 :: 3 :: 4 :: Nil
 2println(nums.indices)
 3for (i <- nums.indices) {
 4  println(s"nums[$i] = ${nums(i)}")
 5}
 6// Expected output:
 7// Range 0 until 4
 8// nums[0] = 1
 9// nums[1] = 2
10// nums[2] = 3
11// nums[3] = 4

列表切分

splitAt(n: Int) 方法表示将列表分成两个部分,第一个部分包含前 n 个元素,第二个部分包含剩余的元素。

1val nums = 1 :: 2 :: 3 :: 4 :: Nil
2val (nums1, nums2) = nums.splitAt(2)
3println(nums1) // List(1, 2)
4println(nums2) // List(3, 4)

列表拼接

::: 操作符用于拼接两个列表,::: 是右结合的,也就是说 a ::: b ::: c 等价于 a ::: (b ::: c)

1val nums1 = 1 :: 2 :: 3 :: Nil
2val nums2 = 4 :: 5 :: 6 :: Nil
3val nums = nums1 ::: nums2
4println(nums) // List(1, 2, 3, 4, 5, 6)

列表翻转

1val nums = 1 :: 2 :: 3 :: 4 :: Nil
2
3// 翻转列表
4println(nums.reverse) // List(4, 3, 2, 1)

列表扁平化

flatten 方法接收一个列表的列表并将它扁平化,返回单个列表,示例如下:

1val list= List(List(1, 2), List(3), List(), List(4, 5)).flatten
2println(list) // List(1, 2, 3, 4, 5)

模式匹配解包

 1val fruit = "apples" :: "oranges" :: "pears" :: Nil
 2
 3val List(a, b, c) = fruit
 4println(a) // apples
 5println(b) // oranges
 6println(c) // pears
 7
 8val d :: e :: rest = fruit
 9println(d) // apples
10println(e) // oranges
11println(rest) // List(pears)

转换为字符串

toSting 方法和 mkString 方法用于将列表转换成字符串。

1val nums = 1 :: 2 :: 3 :: 4 :: Nil
2println(nums.toString) // List(1, 2, 3, 4)
3println(nums.mkString(", ")) // 1, 2, 3, 4

转换为数组

列表的 toArray 方法用于将列表转换为数组:

1val list = 1 :: 2 :: 3 :: 4 :: Nil
2val array = list.toArray
3println(array.mkString(", ")) // 1, 2, 3, 4

数组的 toList 方法用于将数组转换为列表:

1val array = Array(1, 2, 3, 4)
2val list = array.toList
3println(list) // List(1, 2, 3, 4)

列表的 copyToArray(xs, start) 方法用于将列表复制到数组 xs 中下标 start 开始的位置:

1val list = 1 :: 2 :: 3 :: 4 :: Nil
2val array = Array.ofDim[Int](10)
3list.copyToArray(array, 5)
4println(array.mkString(", ")) // 0, 0, 0, 0, 0, 1, 2, 3, 4, 0

List 伴生对象

List 伴生对象的 apply 方法用于创建一个列表,empty 方法用于创建一个空列表。

1// 创建一个空列表
2println(List.apply()) // List()
3
4// 创建一个包含指定元素的列表
5println(List.apply(1, 2, 3, 4)) // List(1, 2, 3, 4)
6
7// 创建一个包含区间数值的列表
8println(List.range(1, 9, 2)) // List(1, 3, 5, 7)
9println(List.range(9, 1, -3)) // List(9, 6, 3)

ListBuffer 基本操作

 1import scala.collection.mutable.ListBuffer
 2
 3object Main extends App {
 4  var listBuffer = new ListBuffer[Int]()
 5
 6  // 在尾部追加一个元素 3
 7  listBuffer += 3 // ListBuffer(3)
 8
 9  // 在尾部追加一个元素 4
10  listBuffer += 4 // ListBuffer(3, 4)
11
12  // 在头部追加一个元素 2
13  2 +=: listBuffer // ListBuffer(2, 3, 4)
14
15  // 在头部插入一个元素 1
16  1 +=: listBuffer // ListBuffer(1, 2, 3, 4)
17
18  // 将 ListBuffer 转换为 List
19  println(listBuffer.toList) // List(1, 2, 3, 4)
20}

ArrayBuffer 基本操作

 1import scala.collection.mutable.ArrayBuffer
 2
 3object Main extends App {
 4  var arrayBuffer = new ArrayBuffer[Int]()
 5
 6  // 在尾部追加一个元素 3
 7  arrayBuffer += 3 // ArrayBuffer(3)
 8
 9  // 在尾部追加一个元素 4
10  arrayBuffer += 4 // ArrayBuffer(3, 4)
11
12  // 在头部追加一个元素 2
13  2 +=: arrayBuffer // ArrayBuffer(2, 3, 4)
14
15  // 在头部插入一个元素 1
16  1 +=: arrayBuffer // ArrayBuffer(1, 2, 3, 4)
17
18  // 将 ArrayBuffer 转换为 List
19  println(arrayBuffer.toList) // List(1, 2, 3, 4)
20
21  // 将 ArrayBuffer 转换为 Array
22  println(arrayBuffer.toArray.mkString(", ")) // 1, 2, 3, 4
23
24}

元组基本操作

元组(Tuple)相比于列表和数组来说,它的元素是异构的,也就是说元组的元素可以是不同类型的。

要访问元组的元素,可以使用 _1 访问第一个元素、使用 _2 访问第二个元素,以此类推。

 1// 创建一个元组
 2val tuple = ("scala", 1024, 3.14, List(1, 2, 3))
 3
 4// 打印元组的第一个元素
 5println(tuple._1) // scala
 6
 7// 打印元组的第二个元素
 8println(tuple._2) // 1024
 9
10// 打印元组的第三个元素
11println(tuple._3) // 3.14
12
13// 打印元组的第四个元素
14println(tuple._4) // List(1, 2, 3)

可以在一条赋值语句中将元组的元素赋值给多个变量,例如:

1val tuple = ("scala", 1024, 3.14, List(1, 2, 3))
2val (s, i, d, l) = tuple
3println(s) // scala
4println(i) // 1024
5println(d) // 3.14
6println(l) // List(1, 2, 3)

注意,上述赋值语句左侧中的圆括号 () 不能省略,省略则表示左侧所有变量都通过右侧的表达式进行初始化:

1val tuple = ("scala", 1024, 3.14, List(1, 2, 3))
2val s, i, d, l = tuple
3println(s) // (scala,1024,3.14,List(1, 2, 3))
4println(i) // (scala,1024,3.14,List(1, 2, 3))
5println(d) // (scala,1024,3.14,List(1, 2, 3))
6println(l) // (scala,1024,3.14,List(1, 2, 3))

可以使用占位符 _ 来忽略元组中的某些元素,例如:

1val tuple = ("scala", 1024, 3.14, List(1, 2, 3))
2val (s, i, _, _) = tuple
3println(s) // scala
4println(i) // 1024

总结

  • Scala 集合框架提供了不可变和可变两个版本,默认使用不可变的集合框架。如果需要使用可变版本,则需要手动从 scala.collection.immutable 包中导入。
上一页
下一页