Scala 数组
在 Scala 中,数组(Array)是一种可变的、固定长度的序列数据结构,用于存储同一类型的元素。Scala 的数组基于 Java 的数组实现,但提供了更丰富的操作接口,结合了命令式和函数式编程特性。以下是对 Scala 数组的中文讲解,内容简洁清晰,涵盖定义、操作、特性及注意事项,适合初学者理解。
1. 数组概述
- 定义:数组是固定长度的有序元素集合,元素通过索引(从 0 开始)访问,支持读写操作。
- 特点:
- 可变性:数组元素可以修改(与 Scala 的不可变集合如
List
不同)。 - 固定长度:创建后长度不可更改。
- 类型安全:所有元素必须是同一类型(如
Int
,String
)。 - 基于 Java 的
Array
类,但 Scala 提供更高级的 API。 - 用途:适合需要索引访问或修改元素的场景,如数据处理或算法实现。
2. 数组的定义与初始化
Scala 数组使用 Array
类定义,支持多种初始化方式。
1. 使用 new Array
- 语法:
val 数组名 = new Array[类型](长度)
- 示例:
val numbers = new Array[Int](3) // 创建长度为 3 的 Int 数组
numbers(0) = 1 // 设置元素
numbers(1) = 2
numbers(2) = 3
println(numbers.mkString(", ")) // 输出: 1, 2, 3
2. 使用 Array()
构造器
- 直接指定初始值,长度由元素个数决定。
- 语法:
val 数组名 = Array(元素1, 元素2, ...)
- 示例:
val fruits = Array("apple", "banana", "orange")
println(fruits(0)) // 输出: apple
3. 类型推断
- Scala 支持类型推断,省略类型声明:
val mixed = Array(1, "Scala", true) // 推断为 Array[Any]
println(mixed.mkString(", ")) // 输出: 1, Scala, true
4. 多维数组
- 使用
Array.ofDim
创建多维数组:
val matrix = Array.ofDim[Int](2, 3) // 2x3 矩阵
matrix(0)(0) = 1
matrix(1)(2) = 5
println(matrix(0)(0)) // 输出: 1
3. 数组操作
Scala 数组支持丰富的操作,包括索引访问、修改、遍历和函数式方法。
1. 访问与修改
- 使用
(索引)
访问或修改元素:
val arr = Array(10, 20, 30)
println(arr(1)) // 输出: 20
arr(1) = 25 // 修改
println(arr(1)) // 输出: 25
2. 遍历数组
- for 循环:
val arr = Array("a", "b", "c")
for (x <- arr) println(x)
// 输出:
// a
// b
// c
- 索引遍历:
for (i <- arr.indices) println(s"Index $i: ${arr(i)}")
// 输出:
// Index 0: a
// Index 1: b
// Index 2: c
- foreach 方法:
arr.foreach(println) // 输出: a, b, c
3. 常用方法
- 长度:
length
或size
获取数组长度。
val arr = Array(1, 2, 3)
println(arr.length) // 输出: 3
- 连接:
mkString
将数组元素拼接为字符串。
println(arr.mkString(", ")) // 输出: 1, 2, 3
- 添加元素:数组长度固定,无法直接添加,但可创建新数组:
val arr = Array(1, 2)
val newArr = arr :+ 3 // 追加
println(newArr.mkString(", ")) // 输出: 1, 2, 3
- 函数式操作:
map
:转换元素。scala val doubled = arr.map(_ * 2) println(doubled.mkString(", ")) // 输出: 2, 4, 6
filter
:筛选元素。scala val evens = arr.filter(_ % 2 == 0) println(evens.mkString(", ")) // 输出: 2
sum
,max
,min
:数值数组的聚合操作。scala println(arr.sum) // 输出: 6 println(arr.max) // 输出: 3
4. 数组排序
- 使用
sorted
(创建新数组)或sortInPlace
(原地排序,Scala 3)。
val arr = Array(3, 1, 2)
val sorted = arr.sorted
println(sorted.mkString(", ")) // 输出: 1, 2, 3
4. 数组的特点
- 可变性:数组元素可修改,但长度固定。
val arr = Array(1, 2, 3)
arr(0) = 10 // 修改
// arr = Array(4, 5) // 错误:不能重新赋值整个数组(除非用 var)
- 与集合的区别:
- 数组是可变的,适合命令式编程。
- 不可变集合(如
List
)更适合函数式编程。 - 性能:数组基于 Java 数组,索引访问效率高(O(1)),适合高性能场景。
5. 注意事项
- 固定长度:数组长度不可变,需用
List
或Vector
处理动态长度需求。 - 类型安全:数组元素类型必须一致,否则推断为
Any
:
val mixed = Array(1, "Scala") // Array[Any]
- 越界检查:访问非法索引会抛出
ArrayIndexOutOfBoundsException
:
val arr = Array(1, 2)
// println(arr(2)) // 错误:索引越界
- 函数式替代:Scala 鼓励使用不可变集合(如
List
)和函数式方法(如map
,filter
)。 - Scala 2 vs Scala 3:
- Scala 3 引入
sortInPlace
等新方法,语法更简洁。 - 类型推断和错误提示更友好。
- 与 Java 数组:Scala 数组直接映射到 Java 数组,兼容 Java 库。
6. 实践示例
综合示例,展示数组的创建和操作:
object ArrayDemo {
def main(args: Array[String]): Unit = {
// 创建数组
val numbers = Array(3, 1, 4, 2)
println(s"Original: ${numbers.mkString(", ")}") // 输出: 3, 1, 4, 2
// 修改元素
numbers(0) = 10
println(s"Modified: ${numbers.mkString(", ")}") // 输出: 10, 1, 4, 2
// 遍历
println("For loop:")
for (x <- numbers) println(x)
// 函数式操作
val doubled = numbers.map(_ * 2)
println(s"Doubled: ${doubled.mkString(", ")}") // 输出: 20, 2, 8, 4
// 排序
val sorted = numbers.sorted
println(s"Sorted: ${sorted.mkString(", ")}") // 输出: 1, 2, 4, 10
// 多维数组
val matrix = Array.ofDim[Int](2, 2)
matrix(0)(0) = 1
matrix(1)(1) = 4
println(s"Matrix: ${matrix.map(_.mkString(", ")).mkString("; ")}")
// 输出: 1, 0; 0, 4
}
}
7. 学习建议
- 实践:在 Scala REPL(运行
scala
命令)中测试数组操作,尝试map
,filter
和多维数组。 - 函数式思维:优先考虑不可变集合(如
List
),仅在需要可变性时使用数组。 - 性能优化:数组适合高性能索引访问,但注意越界错误。
- 资源:
- 官方文档:https://www.scala-lang.org/
- Scala Exercises (https://www.scala-exercises.org/)
- 《Programming in Scala》by Martin Odersky
如果需要深入讲解某一方面(如多维数组或与 List
的对比)或更多示例,请告诉我!