Scala Collection

在 Scala 中,集合(Collections)是用于存储和操作一组数据的核心数据结构。Scala 的集合体系非常强大,结合了面向对象和函数式编程的特点,提供了丰富的可变和不可变集合类型,支持高效的遍历、转换和聚合操作。以下是对 Scala 集合的中文讲解,内容简洁清晰,涵盖分类、常用集合、操作方法及注意事项,适合初学者理解。


1. 集合概述

  • 定义:集合是存储一组相同或不同类型元素的容器,如列表、数组、集合、映射等。
  • 特点
  • 可变 vs 不可变
    • 不可变集合(默认,scala.collection.immutable):元素和结构不可修改,操作返回新集合。
    • 可变集合scala.collection.mutable):允许修改元素或结构。
  • 类型安全:集合元素类型由泛型指定,支持类型推断。
  • 函数式支持:提供 map, filter, fold 等函数式方法,鼓励无副作用操作。
  • 层次结构:所有集合继承自 scala.collection.Iterable,分为 Seq, Set, Map 等。
  • 用途:数据存储、处理、转换,广泛用于算法、数据分析(如 Spark)等。

2. 集合分类

Scala 的集合体系分为不可变和可变两类,主要类型如下:

分类描述不可变示例可变示例
Seq有序序列,元素可重复List, Vector, RangeArrayBuffer, ListBuffer
Set无序集合,元素不重复Set (默认 HashSet)mutable.Set, mutable.HashSet
Map键值对集合,键不重复Map (默认 HashMap)mutable.Map, mutable.HashMap

3. 常用集合类型及用法

1. List(列表)

  • 特点:不可变、线性存储、顺序访问,适合递归操作。
  • 定义
  val list = List(1, 2, 3)
  val list2 = 4 :: list // 添加元素,生成新列表: List(4, 1, 2, 3)
  • 操作
  println(list.head) // 输出: 1
  println(list.tail) // 输出: List(2, 3)
  println(list :+ 4) // 追加: List(1, 2, 3, 4)
  println(0 +: list) // 前置: List(0, 1, 2, 3)

2. Array(数组)

  • 特点:可变、固定长度、索引访问(详见前文数组讲解)。
  • 定义
  val arr = Array(1, 2, 3)
  arr(0) = 10 // 修改
  println(arr.mkString(", ")) // 输出: 10, 2, 3

3. Vector

  • 特点:不可变、随机访问效率高,适合大数据量。
  • 定义
  val vec = Vector(1, 2, 3)
  println(vec(1)) // 输出: 2
  println(vec :+ 4) // 输出: Vector(1, 2, 3, 4)

4. Set(集合)

  • 特点:无序、元素不重复,适合去重或快速查找。
  • 定义
  val set = Set(1, 2, 2, 3) // 输出: Set(1, 2, 3)
  println(set.contains(2)) // 输出: true
  println(set + 4) // 输出: Set(1, 2, 3, 4)

5. Map(映射)

  • 特点:键值对存储,键唯一,适合快速查找。
  • 定义
  val map = Map("Alice" -> 90, "Bob" -> 85)
  println(map("Alice")) // 输出: 90
  println(map + ("Charlie" -> 95)) // 输出: Map(Alice -> 90, Bob -> 85, Charlie -> 95)

6. ArrayBuffer(可变数组缓冲)

  • 特点:可变、动态长度,适合频繁追加/删除。
  • 定义
  import scala.collection.mutable.ArrayBuffer
  val buffer = ArrayBuffer(1, 2, 3)
  buffer += 4 // 追加
  buffer(0) = 10 // 修改
  println(buffer) // 输出: ArrayBuffer(10, 2, 3, 4)

4. 常用集合操作

Scala 集合支持丰富的函数式操作,简化数据处理:

1. 遍历

  • foreach:对每个元素执行操作,无返回值。
  List(1, 2, 3).foreach(println) // 输出: 1, 2, 3

2. 转换

  • map:转换每个元素,返回新集合。
  val doubled = List(1, 2, 3).map(_ * 2)
  println(doubled) // 输出: List(2, 4, 6)
  • flatMap:转换并展平嵌套集合。
  val nested = List(List(1, 2), List(3, 4))
  println(nested.flatMap(x => x)) // 输出: List(1, 2, 3, 4)

3. 过滤

  • filter:筛选符合条件的元素。
  val evens = List(1, 2, 3, 4).filter(_ % 2 == 0)
  println(evens) // 输出: List(2, 4)

4. 聚合

  • reduce:将集合归约为单个值。
  val sum = List(1, 2, 3).reduce(_ + _)
  println(sum) // 输出: 6
  • fold:带初始值的归约。
  val sumWithInitial = List(1, 2, 3).fold(10)(_ + _)
  println(sumWithInitial) // 输出: 16(10 + 1 + 2 + 3)

5. 其他操作

  • 排序sortedsortBy
  val sorted = List(3, 1, 2).sorted
  println(sorted) // 输出: List(1, 2, 3)
  • 分组groupBy
  val grouped = List(1, 2, 3, 4).groupBy(_ % 2)
  println(grouped) // 输出: Map(0 -> List(2, 4), 1 -> List(1, 3))
  • 合并++, concat
  val merged = List(1, 2) ++ List(3, 4)
  println(merged) // 输出: List(1, 2, 3, 4)

5. 注意事项

  • 不可变优先:Scala 默认导入 scala.collection.immutable,鼓励使用不可变集合以减少副作用。
  • 示例:List 是不可变的,修改操作返回新列表。
  • 可变集合:需显式导入 scala.collection.mutable,如 ArrayBuffer
  • 性能
  • List:适合头部操作,尾部追加较慢。
  • Vector:随机访问和更新效率高。
  • ArrayBuffer:适合动态追加/删除。
  • 类型推断
  • 混合类型推断为 Any
    scala val mixed = List(1, "Scala") // List[Any]
  • 建议显式指定类型以提高可读性。
  • 空集合
  • List()Set()Map() 表示空集合。
  • 检查空:isEmptynonEmpty
  • Scala 2 vs Scala 3
  • Scala 3 优化了集合 API,for 推导式更简洁。
  • Scala 3 默认返回类型更一致(如 List 而非 Vector)。
  • 与 Java 互操作:Scala 集合可通过 scala.jdk.CollectionConverters 转换为 Java 集合。

6. 实践示例

综合示例,展示常见集合和操作:

import scala.collection.mutable.ArrayBuffer

object CollectionDemo {
  def main(args: Array[String]): Unit = {
    // List
    val list = List(1, 2, 3, 4)
    println(s"List: ${list.map(_ * 2)}") // 输出: List(2, 4, 6, 8)

    // ArrayBuffer
    val buffer = ArrayBuffer(1, 2, 3)
    buffer += 4
    println(s"ArrayBuffer: $buffer") // 输出: ArrayBuffer(1, 2, 3, 4)

    // Set
    val set = Set(1, 2, 2, 3)
    println(s"Set: ${set + 4}") // 输出: Set(1, 2, 3, 4)

    // Map
    val map = Map("Alice" -> 90, "Bob" -> 85)
    println(s"Map: ${map + ("Charlie" -> 95)}") // 输出: Map(Alice -> 90, Bob -> 85, Charlie -> 95)

    // 函数式操作
    val numbers = List(1, 2, 3, 4, 5)
    val filtered = numbers.filter(_ % 2 == 0)
    val sum = numbers.reduce(_ + _)
    println(s"Filtered: $filtered, Sum: $sum") // 输出: Filtered: List(2, 4), Sum: 15
  }
}

7. 学习建议

  • 实践:在 Scala REPL(运行 scala 命令)中测试集合操作,尝试 map, filter, fold
  • 函数式思维:优先使用不可变集合,结合函数式方法,减少副作用。
  • 性能选择:根据场景选择集合(List 适合递归,Vector 适合随机访问,ArrayBuffer 适合动态修改)。
  • 资源
  • 官方文档:https://www.scala-lang.org/
  • Scala Exercises (https://www.scala-exercises.org/)
  • 《Programming in Scala》by Martin Odersky

如果需要深入讲解某一集合(如 MapVector)或具体操作(如 flatMap),请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注