Skip to content

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)
  }
}

最佳实践

  1. 选择合适的数据结构

    • 固定大小且需要随机访问:使用 Array
    • 动态大小:使用 ArrayBuffer
    • 不可变且函数式操作:使用 ListVector
  2. 性能考虑

    • 数组提供 O(1) 的随机访问
    • 避免频繁的大小调整操作
    • 使用 ArrayBuffer 进行动态构建
  3. 内存效率

    • 数组在内存中是连续存储的
    • 避免不必要的数组复制
    • 考虑使用原始类型数组(如 Array[Int]
  4. 函数式编程

    • 优先使用 mapfilterreduce 等高阶函数
    • 避免可变状态和副作用
    • 使用不可变的集合类型
  5. 错误处理

    • 使用 lift 方法进行安全访问
    • 检查数组边界
    • 使用 Option 类型处理可能的空值

数组是 Scala 中重要的数据结构,理解其特性和最佳使用方式对于编写高效的程序至关重要。

本站内容仅供学习和研究使用。