本节主要学习数组Array集合的概念和相关操作。
一 、数组简介
- 数组允许保存一个序列的元素,并使用从零开始的下标高效地访问(获取或更新)指定位置的元素值
- 数组是Seq的子类。Seq是一个有先次序的值的序列,具有一定长度的可迭代访问的对象。
- 数组分成不可变数组(定长数组)和可变数组(不定长数组)
- 继承关系
- 不可变数组:
Array -> FallbackArrayBuilding -> ArraySeq -> IndexedSeq -> Seq -> Iterable -> Traversable - 可变数组
ArrayBuffer -> Buffer -> Seq ->Iterable -> Traversable
- 不可变数组:
- 数组的特点:访问数组的元素、在尾部添加/删除元素的操作很高效,但是在其他任意位置添加或者删除元素的效率很低,在添加/删除的位置之后的元素都需要被移动。(数组在底层开辟是一块连续的空间)
二、定长数组
- 1.创建定长数组
//定义数组 val nums1 = new Array[Int](10) //10个整数的数组,所有元素初始化为0 val strs1 = new Array[String](10) // 10个字符串的数组,所有元素初始化为null //初始化 nums1(0) = 1 //集合元素采用小括号访问 //定义数组的同时初始化 val nums2: Array[Int] = Array(1,2) val strs2: Array[String] = Array("Hello","Scala") //初始化,可以省略变量的类型,会自动推断出来。 val nums2 = Array(1,2) val strs2 = Array("Hello","World")
- 2.访问数组
使用小括号访问() , 不能使用方括号[]。注意和java的区别(java是[])nums1(1) = 2 nums2(0) nums2(1) strs1(0)
- 3.遍历数组
- ① for循环遍历
for(i <- 区间)val nums = Array(1,2,3,4,5) for(i <- 0 until nums.length){ //until不包含最后一个元素 println(nums(i)) } for(i <- 0 to nums.length -1){ println(nums(i)) }
- ②增强for:如果循环体中不需要使用数组下标
for(num <- nums){ prinlnt(num) }
- 获取区间的方法
- 正序区间
0 until nums.length 或 0 to nums.length-1 或者 nums.indices 。 三者等价 - 倒序区间
0 until nums.length by -1 或 0 to nums.length-1 by -1 或者 nums.indices.reverse
- 正序区间
- ① for循环遍历
三、变长数组
-
1.创建变长数组:需要先导入包 scala.collection.mutable.ArrayBuffer,否则无法直接使用ArrayBuffer
import scala.collection.mutable.ArrayBuffer val b = ArrayBuffer[Int]() //声明整数变长数组 val c = ArrayBuffer(1,2,3) //声明变长数组并赋值。
-
2.尾部添加元素
① 使用"+="b += 1 //添加单个元素 b +=(2,3,4,5) //添加多个元素,元素用括号()包起来
②使用append()
c.append(4) //添加单个元素 c.append(5,6,7) //添加多个元素
-
3.尾部添加集合"++=":
b ++= Array(6,7,8) //添加Array集合 b ++= List(9,10) //添加List集合 b ++= Set(11,12,13) //添加Set集合
注意: 没有 b ++= (1,2,3) 这这样的操作,需要指明集合的类型。
-
4.任意位置移除/添加元素
① 尾部/头部 移除n个元素:trimEnd(n: Int) 、 trimStart()b.trimEnd(2) //移除尾部两个元素 b.trimStart(2) //移除头部两个元素
②指定任意位置移除n个元素:remove()
b.remove(2) //移除b(2)元素 b.remove(2,3)//移除从b(2),b(3),b(4)三个元素
③指定位置添加元素:insert()
b.insert(2,5) // 在b(2)之后添加元素5 b.insert(2,6,7,8) //在b(2)之后添加6,7,8三个元素
-
5.Array和ArrayBuffer相互转换
b.toArray //Array => ArrayBuffer b.toBuffer //ArrayBuffer => Array
注意:b仍然是ArrayBuffer类型的 (val b)。转化后的新类型需要使用新的变量接收。
四、数组转换
对一个已有的数组,以某种方式对它进行转换操作,转换操作不会破坏原式数组,而是得到新的数组
-
① for/yield 循环
val nums = Array(1,2,3,4,5) //for/yield val newNums1 = for(num <- nums) yield 2 * num // newNums1 = Array(2, 4, 6, 8, 10) //for守卫 val newNums2 = for(num <- nums if num % 2 == 0) yield 2 * num // newNums2 = Array(4, 8)
-
② filter/map。有经验的程序员喜欢使用filter+map ,而不是守卫for+yield。但是这只是风格不同,最后都能得到相同的结果,可以根据自己的喜好选择。
val newNums3 = nums.filter(_ % 2 == 0).map(2 * _)
五、常用方法
-
1.求和\最值: sum min max
b.sum b.min b.max
-
2.排序
①调用 sortedb.sorted //注意 b 是val修饰 b本身没有改变。
②sortWith()
val newB = b.sortWith(_>_) //从大到小排序
②调用scala.util.Sorting.quickSort()
注意:不能对ArrayBuffer调用quickSort()val newB = b.toArray scala.util.Sorting.quickSort(newB)
这里有点难理解:newB虽然是val修饰的,quickSort(newB)后,newB本身已经发生了变化。而使用b.sorted方法,b本身不会发生改变。
原因在于:quickSort()方法底层源码是直接对原数组进行修改,所以newB虽然是用val修饰的,它的引用是没有改变,但是引用值发生了改变。sorted方法不会直接对原数组进行操作,而是创建了一个新的变长数组进行追加操作。所以b原数组的引用和引用值都不会发生变化,排序后的新数组需要用一个变量接收。
六、多维数组
和Java一样,多维数组是通过对数组的数组来实现的。
- 构建二维数组: ofDim
//创建二维数组 val matrix = Array.ofDim[Double](3,4) //构建一个三行四列的Double类型的二维矩阵 //访问二维数组 matrix(row)(column) = 42
- 构建不规则的二维数组
val triangle = new Array[Array[Int]](10) for(i <- triangle.indices){ triangle(i) = new Array[Int](i+1) }