Scala 数组
数组是存储相同类型元素的固定大小的数据结构。在 Scala 中,数组对应 Java 的数组,是可变的,但大小固定。
数组基础
数组创建
scala
object ArrayCreation {
def main(args: Array[String]): Unit = {
// 创建数组的不同方式
val arr1 = Array(1, 2, 3, 4, 5)
val arr2 = Array.apply(1, 2, 3, 4, 5)
val arr3 = new Array[Int](5) // 创建长度为5的数组,默认值为0
val arr4 = Array.fill(5)(0) // 用0填充长度为5的数组
val arr5 = Array.tabulate(5)(i => i * i) // 使用函数生成数组
println(s"arr1: ${arr1.mkString(", ")}")
println(s"arr2: ${arr2.mkString(", ")}")
println(s"arr3: ${arr3.mkString(", ")}")
println(s"arr4: ${arr4.mkString(", ")}")
println(s"arr5: ${arr5.mkString(", ")}")
// 不同类型的数组
val stringArray = Array("hello", "world", "scala")
val doubleArray = Array(1.1, 2.2, 3.3)
val booleanArray = Array(true, false, true)
println(s"String array: ${stringArray.mkString(", ")}")
println(s"Double array: ${doubleArray.mkString(", ")}")
println(s"Boolean array: ${booleanArray.mkString(", ")}")
// 多维数组
val matrix = Array.ofDim[Int](3, 4) // 3x4的二维数组
val cube = Array.ofDim[Int](2, 3, 4) // 2x3x4的三维数组
println(s"Matrix dimensions: ${matrix.length} x ${matrix(0).length}")
println(s"Cube dimensions: ${cube.length} x ${cube(0).length} x ${cube(0)(0).length}")
}
}数组访问和修改
scala
object ArrayAccess {
def main(args: Array[String]): Unit = {
val numbers = Array(10, 20, 30, 40, 50)
// 访问元素
println(s"First element: ${numbers(0)}")
println(s"Last element: ${numbers(numbers.length - 1)}")
println(s"Array length: ${numbers.length}")
// 修改元素
numbers(0) = 100
numbers(numbers.length - 1) = 500
println(s"Modified array: ${numbers.mkString(", ")}")
// 安全访问(避免越界)
def safeGet(arr: Array[Int], index: Int): Option[Int] = {
if (index >= 0 && index < arr.length) Some(arr(index))
else None
}
println(s"Safe get index 2: ${safeGet(numbers, 2)}")
println(s"Safe get index 10: ${safeGet(numbers, 10)}")
// 使用 lift 方法
val lifted = numbers.lift
println(s"Lift index 2: ${lifted(2)}")
println(s"Lift index 10: ${lifted(10)}")
}
}数组操作
基本操作
scala
object BasicArrayOperations {
def main(args: Array[String]): Unit = {
val arr = Array(1, 2, 3, 4, 5)
// 基本属性
println(s"Length: ${arr.length}")
println(s"Is empty: ${arr.isEmpty}")
println(s"Non empty: ${arr.nonEmpty}")
// 查找操作
println(s"Contains 3: ${arr.contains(3)}")
println(s"Index of 3: ${arr.indexOf(3)}")
println(s"Last index of 3: ${arr.lastIndexOf(3)}")
// 头尾操作
println(s"Head: ${arr.head}")
println(s"Tail: ${arr.tail.mkString(", ")}")
println(s"Last: ${arr.last}")
println(s"Init: ${arr.init.mkString(", ")}")
// 切片操作
println(s"Slice(1, 4): ${arr.slice(1, 4).mkString(", ")}")
println(s"Take(3): ${arr.take(3).mkString(", ")}")
println(s"Drop(2): ${arr.drop(2).mkString(", ")}")
println(s"Take right(2): ${arr.takeRight(2).mkString(", ")}")
println(s"Drop right(2): ${arr.dropRight(2).mkString(", ")}")
// 反转
println(s"Reverse: ${arr.reverse.mkString(", ")}")
// 排序
val unsorted = Array(5, 2, 8, 1, 9)
println(s"Sorted: ${unsorted.sorted.mkString(", ")}")
println(s"Sorted descending: ${unsorted.sortWith(_ > _).mkString(", ")}")
}
}函数式操作
scala
object FunctionalArrayOperations {
def main(args: Array[String]): Unit = {
val numbers = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// map - 变换每个元素
val doubled = numbers.map(_ * 2)
println(s"Doubled: ${doubled.mkString(", ")}")
// filter - 过滤元素
val evens = numbers.filter(_ % 2 == 0)
println(s"Even numbers: ${evens.mkString(", ")}")
// find - 查找第一个匹配的元素
val firstEven = numbers.find(_ % 2 == 0)
println(s"First even: $firstEven")
// exists - 检查是否存在满足条件的元素
val hasEven = numbers.exists(_ % 2 == 0)
println(s"Has even numbers: $hasEven")
// forall - 检查是否所有元素都满足条件
val allPositive = numbers.forall(_ > 0)
println(s"All positive: $allPositive")
// reduce - 归约操作
val sum = numbers.reduce(_ + _)
val max = numbers.reduce(_ max _)
println(s"Sum: $sum")
println(s"Max: $max")
// fold - 带初始值的归约
val product = numbers.fold(1)(_ * _)
val sumWithZero = numbers.fold(0)(_ + _)
println(s"Product: $product")
println(s"Sum with zero: $sumWithZero")
// scan - 扫描操作(保留中间结果)
val runningSum = numbers.scanLeft(0)(_ + _)
println(s"Running sum: ${runningSum.mkString(", ")}")
// partition - 分割
val (evens2, odds) = numbers.partition(_ % 2 == 0)
println(s"Evens: ${evens2.mkString(", ")}")
println(s"Odds: ${odds.mkString(", ")}")
// groupBy - 分组
val grouped = numbers.groupBy(_ % 3)
grouped.foreach { case (remainder, group) =>
println(s"Remainder $remainder: ${group.mkString(", ")}")
}
}
}数组连接和转换
scala
object ArrayConcatenationConversion {
def main(args: Array[String]): Unit = {
val arr1 = Array(1, 2, 3)
val arr2 = Array(4, 5, 6)
// 连接数组
val concatenated = arr1 ++ arr2
println(s"Concatenated: ${concatenated.mkString(", ")}")
// 使用 concat
val concatenated2 = Array.concat(arr1, arr2)
println(s"Concatenated2: ${concatenated2.mkString(", ")}")
// 添加元素
val withPrepended = 0 +: arr1
val withAppended = arr1 :+ 4
println(s"Prepended: ${withPrepended.mkString(", ")}")
println(s"Appended: ${withAppended.mkString(", ")}")
// 转换为其他集合类型
val list = arr1.toList
val vector = arr1.toVector
val set = arr1.toSet
println(s"To List: $list")
println(s"To Vector: $vector")
println(s"To Set: $set")
// 从其他集合类型转换
val fromList = List(7, 8, 9).toArray
val fromRange = (1 to 5).toArray
println(s"From List: ${fromList.mkString(", ")}")
println(s"From Range: ${fromRange.mkString(", ")}")
// 字符串转换
val chars = "hello".toCharArray
val string = chars.mkString
println(s"String to chars: ${chars.mkString(", ")}")
println(s"Chars to string: $string")
}
}多维数组
二维数组操作
scala
object TwoDimensionalArrays {
def main(args: Array[String]): Unit = {
// 创建二维数组
val matrix = Array(
Array(1, 2, 3),
Array(4, 5, 6),
Array(7, 8, 9)
)
// 访问元素
println(s"Element at (1,1): ${matrix(1)(1)}")
// 打印矩阵
def printMatrix(matrix: Array[Array[Int]]): Unit = {
matrix.foreach(row => println(row.mkString("\t")))
}
println("Original matrix:")
printMatrix(matrix)
// 矩阵转置
def transpose(matrix: Array[Array[Int]]): Array[Array[Int]] = {
val rows = matrix.length
val cols = matrix(0).length
val transposed = Array.ofDim[Int](cols, rows)
for (i <- matrix.indices; j <- matrix(i).indices) {
transposed(j)(i) = matrix(i)(j)
}
transposed
}
println("\nTransposed matrix:")
printMatrix(transpose(matrix))
// 矩阵加法
def addMatrices(a: Array[Array[Int]], b: Array[Array[Int]]): Array[Array[Int]] = {
require(a.length == b.length && a(0).length == b(0).length, "Matrices must have same dimensions")
val result = Array.ofDim[Int](a.length, a(0).length)
for (i <- a.indices; j <- a(i).indices) {
result(i)(j) = a(i)(j) + b(i)(j)
}
result
}
val matrix2 = Array(
Array(9, 8, 7),
Array(6, 5, 4),
Array(3, 2, 1)
)
println("\nMatrix addition:")
printMatrix(addMatrices(matrix, matrix2))
// 查找最大值和位置
def findMax(matrix: Array[Array[Int]]): (Int, Int, Int) = {
var maxValue = matrix(0)(0)
var maxRow = 0
var maxCol = 0
for (i <- matrix.indices; j <- matrix(i).indices) {
if (matrix(i)(j) > maxValue) {
maxValue = matrix(i)(j)
maxRow = i
maxCol = j
}
}
(maxValue, maxRow, maxCol)
}
val (maxVal, maxRow, maxCol) = findMax(matrix)
println(s"\nMax value: $maxVal at position ($maxRow, $maxCol)")
}
}数组性能和内存
性能比较
scala
object ArrayPerformance {
def main(args: Array[String]): Unit = {
val size = 1000000
// 数组 vs List 性能比较
def timeOperation[T](operation: => T): (T, Long) = {
val start = System.nanoTime()
val result = operation
val end = System.nanoTime()
(result, end - start)
}
// 创建性能
val (array, arrayTime) = timeOperation(Array.fill(size)(scala.util.Random.nextInt(100)))
val (list, listTime) = timeOperation(List.fill(size)(scala.util.Random.nextInt(100)))
println(s"Array creation: ${arrayTime / 1000000}ms")
println(s"List creation: ${listTime / 1000000}ms")
// 随机访问性能
val index = size / 2
val (arrayAccess, arrayAccessTime) = timeOperation(array(index))
val (listAccess, listAccessTime) = timeOperation(list(index))
println(s"Array random access: ${arrayAccessTime}ns")
println(s"List random access: ${listAccessTime}ns")
// 遍历性能
val (arraySum, arraySumTime) = timeOperation(array.sum)
val (listSum, listSumTime) = timeOperation(list.sum)
println(s"Array sum: ${arraySumTime / 1000000}ms")
println(s"List sum: ${listSumTime / 1000000}ms")
// 内存使用
println(s"\nMemory considerations:")
println(s"Array: Fixed size, mutable elements, efficient random access")
println(s"List: Immutable, efficient prepend, poor random access")
}
}数组缓冲区
scala
import scala.collection.mutable.ArrayBuffer
object ArrayBufferExample {
def main(args: Array[String]): Unit = {
// ArrayBuffer - 可变大小的数组
val buffer = ArrayBuffer[Int]()
// 添加元素
buffer += 1
buffer += 2
buffer ++= Array(3, 4, 5)
println(s"Buffer: ${buffer.mkString(", ")}")
// 插入和删除
buffer.insert(2, 99) // 在索引2处插入99
buffer.remove(0) // 删除索引0的元素
println(s"After insert/remove: ${buffer.mkString(", ")}")
// 转换为数组
val finalArray = buffer.toArray
println(s"Final array: ${finalArray.mkString(", ")}")
// 性能比较:Array vs ArrayBuffer
def buildWithArray(n: Int): Array[Int] = {
var arr = Array[Int]()
for (i <- 1 to n) {
arr = arr :+ i // 每次都创建新数组,效率低
}
arr
}
def buildWithArrayBuffer(n: Int): Array[Int] = {
val buffer = ArrayBuffer[Int]()
for (i <- 1 to n) {
buffer += i // 高效的追加操作
}
buffer.toArray
}
val n = 10000
val (_, arrayTime) = {
val start = System.nanoTime()
buildWithArray(n)
val end = System.nanoTime()
((), end - start)
}
val (_, bufferTime) = {
val start = System.nanoTime()
buildWithArrayBuffer(n)
val end = System.nanoTime()
((), end - start)
}
println(s"\nBuilding array with Array: ${arrayTime / 1000000}ms")
println(s"Building array with ArrayBuffer: ${bufferTime / 1000000}ms")
}
}实际应用示例
图像处理
scala
object ImageProcessing {
// 简化的图像表示(灰度图)
type Image = Array[Array[Int]]
def createImage(width: Int, height: Int, value: Int = 0): Image = {
Array.fill(height, width)(value)
}
def printImage(image: Image): Unit = {
image.foreach(row => println(row.map(v => f"$v%3d").mkString(" ")))
}
// 应用滤镜
def applyFilter(image: Image, filter: Array[Array[Double]]): Image = {
val height = image.length
val width = image(0).length
val filterSize = filter.length
val offset = filterSize / 2
val result = Array.ofDim[Int](height, width)
for (i <- offset until height - offset; j <- offset until width - offset) {
var sum = 0.0
for (fi <- filter.indices; fj <- filter(fi).indices) {
sum += image(i - offset + fi)(j - offset + fj) * filter(fi)(fj)
}
result(i)(j) = math.max(0, math.min(255, sum.toInt))
}
result
}
// 边缘检测滤镜
val edgeFilter = Array(
Array(-1.0, -1.0, -1.0),
Array(-1.0, 8.0, -1.0),
Array(-1.0, -1.0, -1.0)
)
// 模糊滤镜
val blurFilter = Array(
Array(1.0/9, 1.0/9, 1.0/9),
Array(1.0/9, 1.0/9, 1.0/9),
Array(1.0/9, 1.0/9, 1.0/9)
)
def main(args: Array[String]): Unit = {
// 创建测试图像
val image = Array(
Array(100, 100, 100, 100, 100),
Array(100, 200, 200, 200, 100),
Array(100, 200, 255, 200, 100),
Array(100, 200, 200, 200, 100),
Array(100, 100, 100, 100, 100)
)
println("Original image:")
printImage(image)
println("\nAfter edge detection:")
val edges = applyFilter(image, edgeFilter)
printImage(edges)
println("\nAfter blur:")
val blurred = applyFilter(image, blurFilter)
printImage(blurred)
}
}数据分析
scala
object DataAnalysis {
case class Student(name: String, scores: Array[Double]) {
def average: Double = scores.sum / scores.length
def max: Double = scores.max
def min: Double = scores.min
}
def analyzeScores(students: Array[Student]): Unit = {
println("Student Analysis:")
println("=" * 50)
students.foreach { student =>
println(f"${student.name}%15s: Avg=${student.average}%6.2f, Max=${student.max}%6.2f, Min=${student.min}%6.2f")
}
// 班级统计
val allScores = students.flatMap(_.scores)
val classAverage = allScores.sum / allScores.length
val classMax = allScores.max
val classMin = allScores.min
println("\nClass Statistics:")
println(f"Average: $classAverage%.2f")
println(f"Highest: $classMax%.2f")
println(f"Lowest: $classMin%.2f")
// 成绩分布
val ranges = Array(
("A (90-100)", (90.0, 100.0)),
("B (80-89)", (80.0, 89.9)),
("C (70-79)", (70.0, 79.9)),
("D (60-69)", (60.0, 69.9)),
("F (0-59)", (0.0, 59.9))
)
println("\nGrade Distribution:")
ranges.foreach { case (grade, (min, max)) =>
val count = allScores.count(score => score >= min && score <= max)
val percentage = count.toDouble / allScores.length * 100
println(f"$grade%12s: $count%3d students ($percentage%5.1f%%)")
}
}
def main(args: Array[String]): Unit = {
val students = Array(
Student("Alice", Array(95, 87, 92, 88, 91)),
Student("Bob", Array(78, 82, 85, 79, 83)),
Student("Charlie", Array(92, 95, 89, 94, 96)),
Student("Diana", Array(67, 72, 69, 74, 71)),
Student("Eve", Array(88, 91, 85, 89, 87))
)
analyzeScores(students)
}
}最佳实践
选择合适的数据结构:
- 固定大小且需要随机访问:使用
Array - 动态大小:使用
ArrayBuffer - 不可变且函数式操作:使用
List或Vector
- 固定大小且需要随机访问:使用
性能考虑:
- 数组提供 O(1) 的随机访问
- 避免频繁的大小调整操作
- 使用
ArrayBuffer进行动态构建
内存效率:
- 数组在内存中是连续存储的
- 避免不必要的数组复制
- 考虑使用原始类型数组(如
Array[Int])
函数式编程:
- 优先使用
map、filter、reduce等高阶函数 - 避免可变状态和副作用
- 使用不可变的集合类型
- 优先使用
错误处理:
- 使用
lift方法进行安全访问 - 检查数组边界
- 使用
Option类型处理可能的空值
- 使用
数组是 Scala 中重要的数据结构,理解其特性和最佳使用方式对于编写高效的程序至关重要。