Skip to content

Scala 数组

Scala 中的 Array[T] 是一个可变 (mutable)、固定大小、带索引 (indexed) 的 T 类型元素序列。数组通过索引 (从 0 开始) 提供高效的随机访问。它们直接映射到 Java 数组。

注意: 虽然数组在性能关键代码或与 Java 交互时可用且有用,但惯用的 Scala 通常倾向于使用像 Vector 或 List 这样的不可变集合 (immutable collections) 作为通用序列,因为它们更符合函数式编程原则。

你可以通过几种方式创建数组:

// 1. 使用 'new' 指定大小 (元素初始化为默认值: 0, false, null)
val numbers = new Array[Int](5) // 包含 5 个整数的数组,初始化为 0
val flags = new Array[Boolean](3) // 包含 3 个布尔值的数组,初始化为 false
val strings = new Array[String](2) // 包含 2 个 String 的数组,初始化为 null
// 2. 使用伴生对象的 'apply' 工厂方法 (首选)
val names = Array("Alice", "Bob", "Charlie") // 类型推断: Array[String]
val primes = Array(2, 3, 5, 7) // 类型推断: Array[Int]
val mixed = Array(1, "two", 3.0) // 类型推断: Array[Any]
// 3. 创建一个空数组
val emptyInts = Array.empty[Int]

使用括号 () 和索引来访问或更新元素。记住数组是 0-indexed 的。

val fruits = Array("Apple", "Banana", "Orange")
// 访问元素
val firstFruit = fruits(0) // "Apple"
val secondFruit = fruits(1) // "Banana"
// 修改元素 (数组是可变的)
fruits(1) = "Mango"
// 现在 fruits 是 Array("Apple", "Mango", "Orange")
@main def ArrayAccessDemo(): Unit = {
println(s"First fruit: $firstFruit")
println(s"Updated fruits: ${fruits.mkString(", ")}") // mkString 对于显示很有用
// 访问越界会导致 ArrayIndexOutOfBoundsException
// println(fruits(3))
}

你可以使用 for 推导式或标准集合方法来迭代和处理数组。

val data = Array(1.5, 2.0, 3.5, 4.0)
// 使用 for 循环迭代
println("Processing with for loop:")
var sum = 0.0
for (x <- data) {
println(s"Processing $x")
sum += x
}
println(s"Sum: $sum")
// 使用索引迭代
var product = 1.0
for (i <- 0 until data.length) { // 使用 'until' 获取排他范围
product *= data(i)
}
println(s"Product: $product")
// 使用集合方法 (更函数式风格)
val increasedData = data.map(x => x + 0.1)
println(s"Increased data: ${increasedData.mkString(", ")}")
val largeValues = data.filter(x => x > 2.5)
println(s"Large values: ${largeValues.mkString(", ")}")
data.foreach(x => println(s"Element: $x")) // 具有副作用的迭代

Scala 支持使用 Array.ofDim 创建多维数组。

// 创建一个 2x3 的整数矩阵 (2 行, 3 列)
val matrix = Array.ofDim[Int](2, 3)
// 初始化矩阵
for (row <- 0 until matrix.length) {
for (col <- 0 until matrix(row).length) {
matrix(row)(col) = row * 10 + col
}
}
// 打印矩阵
@main def MultiDimArrayDemo(): Unit = {
println("Matrix:")
for (row <- matrix) { // 迭代行 (行本身也是数组)
println(row.mkString("\t")) // 打印每一行
}
// 访问特定元素
println(s"Element at (1, 2): ${matrix(1)(2)}") // 输出: 12
}

输出:

Matrix:
0 1 2
10 11 12
Element at (1, 2): 12

许多有用的方法可以直接使用或通过 Array 伴生对象访问。

方法/操作描述
length获取数组的大小。
apply(index)访问指定索引处的元素 (通过 myArray(index) 语法使用)。
update(index, value)修改指定索引处的元素值 (通过 myArray(index) = value 语法使用)。
map, filter, foreach标准的函数式集合方法。
mkString(sep)将数组元素转换为带有分隔符的字符串。
++连接两个数组 (返回一个新数组)。
head, tail, last, init访问第一个/最后一个元素或子序列。
slice(from, until)提取一个子数组。
sorted返回一个新的已排序数组 (需要 Ordering)。
sum, min, max, product数值数组的聚合方法。
Array.fill(n)(elem)创建一个大小为 n,所有元素为 elem 的数组。
Array.tabulate(n)(f)创建一个大小为 n 的数组,其中元素 i 是 f(i) 的结果。
Array.range(start, end, step)创建一个包含指定范围内元素的数组。
val arr1 = Array(1, 2)
val arr2 = Array(3, 4)
val combined = arr1 ++ arr2 // Array(1, 2, 3, 4)
val evens = Array.range(0, 10, 2) // Array(0, 2, 4, 6, 8)
@main def ArrayOpsDemo(): Unit = {
println(s"Combined: ${combined.mkString(", ")}")
println(s"Evens: ${evens.mkString(", ")}")
}