☰
Scala Array操作:从定长数组到ArrayBuffer的完整指南
2026/11/2 18:52:36 网站建设 项目流程

Scala的Array就是Java数组的封装,但Scala给它装上了集合操作的"超能力"。索引访问、map/filter、与List互转——让数组处理从Java的for循环中解放出来。

如果你从Java转到Scala,第一次用数组时可能会有疑问:Scala的Array和Java的数组是同一个东西吗?为什么可以直接用map和filter?

第一个问题的答案是:是的,Scala的Array编译后就是Java的数组(int[]、String[]),JVM层面完全一样。第二个问题的答案是:Scala通过隐式转换,把Array当作Seq来操作——你写的是数组,用的却是集合的API。

在大数据开发中,数组无处不在:Spark RDD的分区数据是数组、Flink的窗口缓冲区是数组、NumPy风格的数值计算依赖数组。理解Scala的Array,就是理解大数据内存计算的底层数据结构。

这篇文章从七个层面拆解Scala的Array操作,帮你从Java的数组处理中平滑迁移。


01 Array基础:定长、可变、与Java互操作

Array就是Java数组

// Scala的Array编译后就是Java数组valarr=Array(1,2,3,4,5)// 编译后等价于Java的 int[] arr = {1,2,3,4,5};// 可以直接索引访问arr(0)// 1arr(4)// 5// 可以修改元素(数组是可变的)arr(0)=10// arr: Array(10, 2, 3, 4, 5)

Array是定长的

valarr=newArray[Int](5)// 长度固定为5,不能动态扩展arr(0)=1arr(1)=2// arr: Array(1, 2, 0, 0, 0)// arr += 6 // 编译错误:Array长度固定

Array与Java数组互操作

// Scala Array就是Java数组,可以直接传给Java方法defprocessJavaArray(arr:Array[Int]):Unit={// 这个arr在JVM层面就是int[]arr.foreach(println)}// 也可以从Java数组创建Scala ArrayvaljavaArr:Array[Int]=Array(1,2,3)// 完全等价

对Java开发者的启示:Java数组和Scala数组在JVM层面是同一个东西,互操作零成本。这意味着你可以在Scala代码中直接调用Java库,传入数组参数,不需要任何转换。


02 Array创建与初始化

用apply方法创建

// 最常用:Array.applyvalarr1=Array(1,2,3,4,5)// Array[Int] = Array(1, 2, 3, 4, 5)// 混合类型会自动推断公共父类型valarr2=Array(1,"two",3.0)// Array[Any] = Array(1, two, 3.0)// 空数组valempty=Array.empty[String]// Array[String] = Array()

用new创建指定长度

// 创建指定长度的数组,元素为默认值valarr1=newArray[Int](5)// Array(0, 0, 0, 0, 0)valarr2=newArray[String](3)// Array(null, null, null)valarr3=newArray[Boolean](2)// Array(false, false)

常用初始化方法

// range:生成范围数组Array.range(1,10)// Array(1,2,3,4,5,6,7,8,9)Array.range(1,10,2)// Array(1,3,5,7,9),步长2// fill:填充相同值Array.fill(5)("hello")// Array(hello, hello, hello, hello, hello)Array.fill(3,2)(0)// 二维数组 Array(Array(0,0), Array(0,0), Array(0,0))// tabulate:按函数生成Array.tabulate(5)(n=>n*n)// Array(0, 1, 4, 9, 16)// concatenate:合并数组Array.concat(Array(1,2),Array(3,4))// Array(1, 2, 3, 4)

03 Array常用操作

索引访问与修改

valarr=Array(10,20,30,40,50)// 读取arr(0)// 10arr.last// 50arr.head// 10arr.apply(2)// 30,等价于arr(2)// 修改arr(0)=100// arr: Array(100, 20, 30, 40, 50)// 长度arr.length// 5arr.size// 5,等价于length

遍历

valarr=Array("a","b","c")// 最简单:foreacharr.foreach(println)// 带索引for((elem,i)<-arr.zipWithIndex){println(s"$i:$elem")}// 传统for循环for(i<-0until arr.length){println(arr(i))}

转换与映射

valarr=Array(1,2,3,4,5)// map:每个元素转换arr.map(_*2)// Array(2, 4, 6, 8, 10)// filter:过滤元素arr.filter(_%2==0)// Array(2, 4)// reduce:聚合arr.reduce(_+_)// 15// fold:带初始值的聚合arr.fold(0)(_+_)// 15

排序

valarr=Array(3,1,4,1,5,9,2,6)// 升序排序(返回新数组)arr.sorted// Array(1, 1, 2, 3, 4, 5, 6, 9)// 降序arr.sortWith(_>_)// Array(9, 6, 5, 4, 3, 2, 1, 1)// 按指定字段排序caseclassPerson(name:String,age:Int)valpeople=Array(Person("Alice",25),Person("Bob",20),Person("Charlie",30))people.sortBy(_.age)// 按年龄升序

04 ArrayBuffer:可变数组

Array是定长的,需要动态扩展时用ArrayBuffer。

创建与操作

importscala.collection.mutable.ArrayBuffer// 创建ArrayBuffervalbuf=ArrayBuffer[Int]()// ArrayBuffer()// 添加元素buf+=1buf+=2buf+=3// ArrayBuffer(1, 2, 3)// 添加多个元素buf+=(4,5,6)// ArrayBuffer(1, 2, 3, 4, 5, 6)// 追加另一个集合buf++=Array(7,8)// ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8)

删除与修改

valbuf=ArrayBuffer(1,2,3,4,5)// 删除最后一个元素buf.remove(buf.length-1)// ArrayBuffer(1, 2, 3, 4)// 删除指定位置buf.remove(0)// ArrayBuffer(2, 3, 4)// 修改buf(0)=100// ArrayBuffer(100, 3, 4)

转换为Array

valbuf=ArrayBuffer(1,2,3,4,5)// 转换为定长Arrayvalarr=buf.toArray// Array(1, 2, 3, 4, 5)// 转换为Listvallist=buf.toList// List(1, 2, 3, 4, 5)

05 Array与集合互转

Array ↔ List

valarr=Array(1,2,3,4,5)// Array转Listvallist=arr.toList// List(1, 2, 3, 4, 5)// List转Arrayvalarr2=list.toArray// Array(1, 2, 3, 4, 5)// Array转Seqvalseq=arr.toSeq// WrappedArray(1, 2, 3, 4, 5)

Array与集合操作的关系

valarr=Array(1,2,3,4,5)// Array本身不是Seq,但可以通过隐式转换使用Seq的方法arr.map(_*2)// 返回Arrayarr.filter(_>2)// 返回Arrayarr.reduce(_+_)// 返回Intarr.mkString(", ")// "1, 2, 3, 4, 5"// 注意:map/filter返回的还是Arrayarr.map(_*2).getClass.getSimpleName// int[](基本类型数组)或 Object[]

WrappedArray:Array的Seq视图

valarr=Array(1,2,3)// 当你需要Seq类型时,Array会自动转换为WrappedArrayvalseq:Seq[Int]=arr// WrappedArray(1, 2, 3)// WrappedArray是Array的Seq视图,不复制数据// 修改原数组,视图也会变arr(0)=100println(seq)// WrappedArray(100, 2, 3)

大数据场景提示:Spark的RDD.collect()返回的就是Array,而RDD的map/filter返回的是RDD。理解Array和集合操作的关系,有助于理解Spark转换操作的底层实现。


06 多维数组

创建多维数组

// 二维数组:3行4列valmatrix=Array.ofDim[Int](3,4)// Array(Array(0,0,0,0), Array(0,0,0,0), Array(0,0,0,0))// 赋值matrix(0)(0)=1matrix(1)(1)=2// Array(Array(1,0,0,0), Array(0,2,0,0), Array(0,0,0,0))// 创建并初始化valgrid=Array(Array(1,2,3),Array(4,5,6),Array(7,8,9))// 3x3矩阵

多维数组操作

valmatrix=Array(Array(1,2,3),Array(4,5,6),Array(7,8,9))// 访问matrix(0)(0)// 1matrix(1)(2)// 6// 遍历所有元素for{row<-matrix elem<-row}print(elem+" ")// 1 2 3 4 5 6 7 8 9// 扁平化:二维数组转一维matrix.flatten// Array(1, 2, 3, 4, 5, 6, 7, 8, 9)

07 与Java数组的对比

理解Scala和Java数组操作的差异,能帮助你避免常见的迁移陷阱。

核心差异对比

维度JavaScala
数组创建int[] arr = new int[5]Array(1,2,3) 或 new ArrayInt
索引访问arr[0]arr(0)
长度arr.lengtharr.length 或 arr.size
遍历for(int i=0;…)arr.foreach 或 for推导式
转换Arrays.stream(arr)arr.map/filter/reduce
排序Arrays.sort(arr)arr.sorted 或 arr.sortBy
拼接Arrays.toString(arr)arr.mkString(", ")
可变数组ArrayListArrayBuffer
互操作本身就是数组编译后就是Java数组

Java数组操作 vs Scala数组操作

// Java: 数组创建int[]arr=newint[5];arr[0]=1;arr[1]=2;// Java: 数组遍历for(inti=0;i<arr.length;i++){System.out.println(arr[i]);}// Java: 数组排序Arrays.sort(arr);// Java: 数组转字符串System.out.println(Arrays.toString(arr));
// Scala: 数组创建valarr=Array(1,2,3,4,5)// Scala: 数组遍历arr.foreach(println)// Scala: 数组排序arr.sorted// Scala: 数组转字符串arr.mkString(", ")

Scala数组工具方法

// 常用工具方法importscala.util.Sorting.quickSortvalarr=Array(3,1,4,1,5,9,2,6)// 快速排序(原地修改)quickSort(arr)// arr: Array(1, 1, 2, 3, 4, 5, 6, 9)// 数组合并Array.concat(Array(1,2),Array(3,4))// 数组填充Array.fill(5)(0)

写在最后:数组是数据工程的底层数据结构

Scala的Array,表面上是Java数组的"语法糖封装",本质上是把数组从"一个固定大小的内存块"提升为"一个可以函数式操作的集合"。

这种提升带来三个好处:

  1. 更简洁的操作:map/filter/reduce替代了Java的for循环和Stream,代码更易读
  2. 更强的互操作性:Scala Array编译后就是Java数组,与Java库零成本互操作
  3. 更灵活的扩展:ArrayBuffer提供了动态扩展能力,不需要手动管理数组大小

这些特性不是孤立的,它们共同支撑了Scala的数据处理范式。Spark的RDD分区数据是数组、Flink的窗口缓冲区是数组、NumPy风格的数值计算依赖数组——这些框架的底层都是Scala数组操作的分布式版本。

学习建议:不要试图一次记住所有方法。先从数组创建和索引访问开始,写一些小练习。当你习惯了用map/filter处理数组后,再学习ArrayBuffer和多维数组。数组是编程的基本功,但在Scala里,它不仅是基本功——它是函数式数据处理的入口。

从Java的数组遍历和操作,到Scala的map/filter/reduce,不是学习"另一种数组API",而是学习一种"更函数式、更声明式、更组合的数据处理方式"。当你习惯了用Array.apply创建、用foreach遍历、用map转换、用reduce聚合,你会发现:原来数组处理可以这么优雅。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询