目录
- 第十三章 集合
- 1- 列表 (List)
- 2- 集 (Set)
- 3- 映射 (Map)
- 4- 数组 (Array)
- 5- 元组 (Tuple)
- 6- 可变和不可变集合
- 7- 添加或者去除元素
- 8- 化简、折叠和扫描
- 9- 拉链操作
- 10- 迭代器
- end
第十三章 集合
在Scala中, 集合 (Collections) 是一种重要的数据结构, 用于存储和操作一组元素 ;
Scala提供了丰富的集合类库, 包括可变和不可变的集合类型, 以及各种高阶函数和操作符, 方便对集合进行操作和转换 ;
常见的Scala集合类型包括:
- 列表 (List) : 有序集合, 元素可重复, 使用
List
关键字定义 ; - 集 (Set) : 无须集合, 元素不重复, 使用
Set
关键字定义 ; - 映射 (Map) : 键值对集合, 键不重复, 值可重复, 使用
Map
关键字定义 ; - 数组 (Array) : 定长可变集合, 使用
Array
关键字定义 ; - 元组 (Tuple) : 不同类型元素的有序集合, 使用 (value1, value2, …) 定义 ;
1- 列表 (List)
在Scala中, 列表 (List) 是一种不可变的有序集合, 允许元素重复 ;
列表是基于链表结构实现的, 每个列表都由一个头部元素和一个指向剩余元素列表的尾部组成 ;
Scala的列表提供了丰富的操作方法, 如 map
、filter
、foldLeft
等, 用于对列表进行转换和操作 ;
示例:
// 1. 创建列表: 可以使用List关键字创建列表val numbers = List(1, 2, 3, 4, 5)// 2. 访问元素: 可以使用索引访问列表中的元素, 索引从0开始val firstElement = numbers(0)println(firstElement) // 输出: 1// 3. 操作列表: 可以使用map, filter, reduce等方法对列表进行操作val doubledNumbers = numbers.map(_ * 2)println(doubledNumbers) // 输出: List(2, 4, 6, 8, 10)val evenNumbers = numbers.filter(_ % 2 == 0)println(evenNumbers) // 输出: List(2, 4)val sum = numbers.reduce(_ + _)println(sum) // 输出: 15// 4. 连接列表: 可以使用 `::` 操作符将元素添加到列表的开头val newNumbers = 0 :: numbersprintln(newNumbers) // 输出: List(0, 1, 2, 3, 4, 5)// 5. 列表模式匹配: 可以使用模式匹配来处理列表中的元素val (head, tail) = numbers match {case h :: t => (h, t)case _ => (0, Nil)}println(head) // 输出: 1println(tail) // 输出: List(2, 3, 4, 5)
Scala的列表是不可变的, 这意味着列表的内容在创建后不可更改 ;
如果需要可变列表, 可以使用 scala.collection.mutable.ListBuffer
.
2- 集 (Set)
在Scala中, 集合 (Set) 是一种不可变的元素集合, 其中元素不重复 ;
Scala的集合库提供了 Set
特质以及不可变和可变的具体实现, 用于存储一组唯一的元素 ;
集合在Scala中通常用于快速查找和去重操作 ;
示例:
// 1. 创建集合: 可以使用 `Set` 关键字创建集合val numberSet = Set(1, 2, 3, 4, 5)// 2. 添加元素: 集合是不可变的, 无法直接添加元素, 但可以通过创建新的集合来添加元素val newNumberSet = numberSet + 6// 3. 操作集合: 可以使用集合的 `map` 方法来对集合中的每个元素进行操作, `insersect` 方法来求交集, `union` 方法来求并集val otherSet = Set(3, 4, 5, 6, 7)val intersectSet = numberSet.intersect(otherSet)val unionSet = numberSet.union(otherSet)println(intersectSet) // 输出: Set(5, 3, 4)println(unionSet) // 输出: Set(5, 1, 6, 2, 7, 3, 4)// 4. 检查元素: 可以使用 `contains` 方法来检查集合中是否包含某个元素val containsFive = numberSet.contains(5)println(containsFive) // 输出: true// 5. 遍历集合: 可以使用 `foreach` 方法来遍历集合中的每个元素numberSet.foreach(println)// 输出:// 5// 1// 2// 3// 4
Scala的集合库还提供了丰富的方法和操作符, 用于对集合进行操作和转换 ;
集合在Scala中是非常常用且强大的数据结构, 适应于各种场景 .
3- 映射 (Map)
在Scala中, 映射 (Map) 是一种键值对的集合, 用于存储一组唯一的键和对应的值 ;
Scala的映射是基于哈希表实现的, 可以快速查找和访问键值对 ;
映射在Scala中非常常用, 用于表示各种数据关系和映射关系 ;
示例:
// 1. 创建映射: 可以使用 `Map` 关键字创建映射val personInfo = Map("name" -> "Jim", "age" -> 18)// 2. 访问值: 可以通过键访问映射中的值val name = personInfo("name")val age = personInfo.getOrElse("age", 0)println(s"name: $name, age: $age") // name: Jim, age: 18// 3. 添加值: 映射不可变, 无法直接添加键值对, 可以通过创建新的映射来添加键值对, 可以使用 `+` 运算符添加键值对val newPersonInfo = personInfo + ("gender" -> "male")println(newPersonInfo) // Map(name -> Jim, age -> 18, gender -> male)// 4. 操作映射: 可以使用各种方法对映射进行操作, 例如: `keys` 获取所有键, `values` 获取所有值, `contains` 判断是否存在键val keys = personInfo.keysval values = personInfo.valuesprintln(keys) // Set(name, age)println(values) // MapLike(Jim, 18)println(personInfo.contains("name")) // trueprintln(personInfo.contains("gender")) // false// 5. 遍历映射: 可以使用 `foreach` 方法遍历映射, 并执行指定的操作personInfo.foreach {case (key, value) => println(s"$key: $value")}/* 输出结果:name: Jimage: 18*/
Scala的映射提供了丰富的方法和操作符, 用于对键值对进行操作和转换 ;
映射是一种非常有用的数据结构, 适应于各种场景, 如配置信息, 数据索引等 .
4- 数组 (Array)
在Scala中, 数组 (Array) 是一种可变的有序集合, 用于存储固定大小的元素 ;
Scala的数组与Java的数组类似, 但Scala的数组可以是泛型的, 运行存储不同类型的元素 ;
数组在Scala中是一种基本的数据结构, 常用于需要高性能和可变性的场景 ;
示例:
// 1. 创建数组: 可以使用 `Array` 关键字创建数组val numbers = Array(1, 2, 3, 4, 5)// 2. 访问元素: 可以使用索引访问数组中的元素, 索引从0开始val firstNumber = numbers(0)println(firstNumber) // 输出: 1// 3. 更新元素: 由于数组是可变的, 可以使用索引更新数组中的元素numbers(0) = 10println(numbers(0)) // 输出: 10// 4. 操作数组: 可以使用 `map` 方法对数组进行操作, 例如将数组中的每个元素乘以2; `filter` 方法对数组进行过滤, 例如只保留偶数;val doubledNumbers = numbers.map(_ * 2)println(doubledNumbers.mkString(", ")) // 输出: 20, 4, 6, 8, 10val evenNumbers = numbers.filter(_ % 2 == 0)println(evenNumbers.mkString(", ")) // 输出: 2, 4// 5. 遍历数组: 可以使用 `foreach` 方法遍历数组numbers.foreach(println) // 输出: 10 2 3 4 5// 6. 转换为列表: 可以使用 `toList` 方法将数组转换为列表val numbersList = numbers.toListprintln(numbersList) // 输出: List(10, 2, 3, 4, 5)
Scala的数组提供了高性能和可变性, 适应于需要频繁修改元素的场景 ;
但需要注意的是, 数组是可变的数据结构, 可能引入一些副作用, 因此在函数式编程中建议尽量使用不可变的集合 .
5- 元组 (Tuple)
在Scala中, 元组 (Tuple) 是一种不可变的有序集合, 用于存储固定数量的元素 ;
元组可以包含不同类型的元素, 并且元组的长度是固定的 ;
Scala的元组提供了一种方便的方式来组合和传递多个值, 而不需要创建新的类或结构 ;
示例:
// 1. 创建元组: 可以使用小括号和逗号创建元组val person = ("Tom", 18, "London")// 2. 访问元组: 可以使用 `.` 和索引访问元组中的元素, 索引从1开始val name = person._1val age = person._2val city = person._3println(name) // 输出: Tomprintln(age) // 输出: 18println(city) // 输出: London// 3.元组模式匹配: 可以使用模式匹配来解构元组person match {case (name, age, city) => println(s"$name is $age years old, and lives in $city.")}// 输出: Tom is 18 years old, and lives in London.// 4. 元组转换为列表: 可以使用 `.toList` 方法将元组转换为列表val personList = person.productIterator.toListprintln(personList) // 输出: List(Tom, 18, London)// 5. 遍历元组: 可以使用 `.foreach` 方法遍历元组中的每个元素person.productIterator.foreach(println)/* 输出:Tom18London*/
元组的特性: 元组子啊Scala中常用于返回多个值的函数 、临时组合数据等场景 , 具有简洁和灵活的特性 ;
Scala的元组是一种轻量级的数据结构, 适用于需要临时组合多个值的情况 ;
元组的不可变性和固定长度使其在某些场景下非常有用 .
6- 可变和不可变集合
在Scala中, 集合可以分为可变 (mutable) 和不可变 (immutable) 两种类型 ;
不可变集合是指一旦创建就无法更改的集合, 任何修改操作都会返回一个新的集合, 原集合保持不变 ;
相反, 可变集合允许在原地修改其内容, 即可以直接修改集合而不需要创建新的集合 .
不可变集合在Scala中是更常用的选择, 因为他们具有线程安全性和函数式编程的优点 ;
不可变集合的操作不会改变原始集合, 而返回一个新的不可变集合, 这有助于避免副作用和提高代码的可维护性 .
可变集合则适用于需要频繁修改数据的场景, 因为他们允许直接在原地修改集合内容, 而不是创建新的集合 ;
可变集合在某些情况下可以提供更高的性能, 但也需要更多的注意力来管理状态变化 ;
在Scala中, 不可变集合通常位于 scala.collection.immutable
包中, 而可变集合位于 scala.collection.mutable
包中 ;
开发者可以根据具体需求和场景选择合适的集合类型, 以实现更安全、高效的编程 .
7- 添加或者去除元素
在Scala中, 集合中常用的方法用于添加或去除元素包括 +
、+:
和 :+
;
-
+
: 对于不可变无顺序的集合,+
方法用于向集合中添加元素并返回一个新的集合, 原集合保持不变 ; 例如: 对于Set集合:val set = Set(1, 2, 3, 4, 5)val newSet = set + 6println(newSet) // Set(5, 1, 6, 2, 3, 4)
-
+:
: 对于List集合,+:
方法用于在列表的头部添加元素并返回一个新的列表, 原列表保持不变 ; 例如:val list = List(3,4,5)val newList = 1 +: listprintln(newList) // List(1, 3, 4, 5)
-
:+
: 对于List集合,:+
方法用于在列表的尾部添加元素并返回一个新的列表, 原列表保持不变 ; 例如:val list = List(3,4,5)val newList = list :+ 6println(newList) // List(3, 4, 5, 6)
这些操作符都会返回新的集合, 不会修改原有的集合 .
8- 化简、折叠和扫描
在Scala中, 集合的化简 (reduce) 、折叠(fold) 和扫描(scan) 是常用的函数式编程操作, 用于对集合中的元素进行聚合计算 ;
-
化简 (reduce) :
-
reduce
函数将集合中的元素两两结合, 递归地将结果与下一个元素结合, 最终返回一个值 ; -
示例: 对列表中的元素求和
-
val list = List(1, 2, 3, 4, 5)val sum = list.reduce(_ + _)println(sum) // 15
-
-
折叠 (fold) :
-
fold
函数接受一个初始值和一个二元操作函数, 从初始值开始, 将集合中的元素依次应用于操作函数, 返回最终结果 ; -
示例: 对列表中的元素求和, 初始值为 1000
-
val list = List(1, 2, 3, 4, 5)val sum = list.fold(100)((x, y) => x + y) // list.fold(100)(_ + _)println(sum) // 115
-
-
扫描 (scan) :
-
scan
函数类似于fold
, 但会返回每一步的中间结果组成的集合 ; -
示例: 对列表中的元素进行累加扫描
-
val list = List(1, 2, 3, 4, 5)val scanResult = list.scan(-3)(_ + _)println(scanResult) // List(-3, -2, 0, 3, 7, 12)val scanLeftResult = list.scanLeft(-3)(_ + _) // 从左到右println(scanLeftResult) // List(-3, -2, 0, 3, 7, 12)val scanRightResult = list.scanRight(-3)(_ + _) // 从右到左println(scanRightResult) // List(12, 11, 9, 6, 2, -3)
-
9- 拉链操作
在Scala中, 拉链操作 (zip) 是一种常见的集合操作, 用于将两个集合的对应元素进行配对 ;
具体来说, 拉链操作会将两个集合中相同位置的元素组成一个元组, 生成一个新的集合 ;
示例:
val list1 = List(1, 2, 3, 4, 5)val list2 = List("A", "B", "C", "D", "E")val list3 = list1 zip list2println(list3) // List((1,A), (2,B), (3,C), (4,D), (5,E))// 如果两个列表元素个数不同, 以最少的进行匹配val list1 = List(1, 2, 3, 4)val list2 = List("A", "B", "C", "D", "E")val list3 = list1 zip list2println(list3) // List((1,A), (2,B), (3,C), (4,D)
在上面的示例中, list1
和 list2
分别是两个不同类型的集合, 通过 zip
方法进行拉链操作后, 生成了一个包含元组的新集合 list3
, 其中每个元组包含了两个集合对应位置的元素 ;
拉链操作在处理需要将两个集合的元素一一对应的情况下非常有用, 可以方便地将两个集合进行配对操作 .
10- 迭代器
在Scala中, 可以使用迭代器 (Iterator) 来遍历集合 ;
迭代器提供了一种逐个访问集合元素的方式, 适用于需要逐个处理集合元素的场景 ;
示例: 使用迭代器遍历集合的基本方法
val list = List(1, 2, 3, 4, 5)val it = list.iteratorwhile (it.hasNext) {println(it.next())}/* 输出: 12345*/
- 在上面的示例中, 首先创建了一个整数列表
list
, 然后通过iterator
方法获取了该列表的迭代器it
; - 接着使用
while
循环和hasNext
方法判断是否还有下一个元素, 然后使用next
方法逐个访问并处理元素 .
除了使用 while
循环外, 还可以使用 foreach
方法来简化迭代器的遍历:
val list = List(1, 2, 3, 4, 5)val it = list.iteratorit.foreach(println) /*12345*/
通过以上方法, 您可以方便地使用迭代器遍历Scala集合中的元素 .