Scala

Scala-数组-用法详解
- Scala
- 一、数组的定义
-
- [1. `new` 关键字](#1.
new关键字) - [2. `Array` 对象的 `apply` 方法](#2.
Array对象的apply方法) - [3. 创建多维数组](#3. 创建多维数组)
- [1. `new` 关键字](#1.
- 二、数组常用方法
-
- [1. `length`:获取数组的长度。](#1.
length:获取数组的长度。) - [2. `apply`:通过索引获取数组中的元素。](#2.
apply:通过索引获取数组中的元素。) - [3. `update`:通过索引更新数组中的元素。](#3.
update:通过索引更新数组中的元素。) - [4. `foreach`:遍历数组中的每个元素。](#4.
foreach:遍历数组中的每个元素。) - [5. `map`:对数组中的每个元素应用一个函数,并返回一个新的数组。](#5.
map:对数组中的每个元素应用一个函数,并返回一个新的数组。) - [6. `filter`:过滤数组中的元素,返回一个新的数组。](#6.
filter:过滤数组中的元素,返回一个新的数组。) - [7. `foldLeft`:从左到右累积数组中的元素。(fold、foldRight)](#7.
foldLeft:从左到右累积数组中的元素。(fold、foldRight)) - [8. `reduce`:将数组中的元素减少为一个单一的值。](#8.
reduce:将数组中的元素减少为一个单一的值。) - [9. `mkString`:将数组中的元素连接成一个字符串。](#9.
mkString:将数组中的元素连接成一个字符串。) - [10. `sortWith`:根据给定的比较函数对数组进行排序。](#10.
sortWith:根据给定的比较函数对数组进行排序。) - [11. `zip`:将两个数组配对成一个元组数组。](#11.
zip:将两个数组配对成一个元组数组。) - [12. `contains`:检查数组是否包含某个元素。](#12.
contains:检查数组是否包含某个元素。) - [13. `indexOf`:查找数组中某个元素的第一个索引。](#13.
indexOf:查找数组中某个元素的第一个索引。) - [14. `slice`:提取数组的一个子数组。](#14.
slice:提取数组的一个子数组。) - [15. `concat`:连接两个数组。](#15.
concat:连接两个数组。) - [16. `reverse`:反转数组。](#16.
reverse:反转数组。) - [17. `distinct`:去除数组中的重复元素。](#17.
distinct:去除数组中的重复元素。) - [18. `exists`:检查数组中是否存在满足条件的元素。](#18.
exists:检查数组中是否存在满足条件的元素。) - [19. `forall`:检查数组中的所有元素是否都满足某个条件。](#19.
forall:检查数组中的所有元素是否都满足某个条件。) - [20. `find`:查找数组中第一个满足条件的元素,返回 `Option` 类型。](#20.
find:查找数组中第一个满足条件的元素,返回Option类型。) - [21. `count`:计算数组中满足条件的元素的数量。](#21.
count:计算数组中满足条件的元素的数量。) - [22. `min` 和 `max`:分别返回数组中的最小值和最大值。](#22.
min和max:分别返回数组中的最小值和最大值。) - [23. `sum` 和 `product`:分别返回数组中所有元素的总和和乘积。](#23.
sum和product:分别返回数组中所有元素的总和和乘积。) - [24. `partition`:将数组分为两个数组,一个包含满足条件的元素,另一个包含不满足条件的元素。](#24.
partition:将数组分为两个数组,一个包含满足条件的元素,另一个包含不满足条件的元素。) - [25. `groupBy`:根据某个条件将数组中的元素分组。](#25.
groupBy:根据某个条件将数组中的元素分组。) - [26. `flatMap`:对数组中的每个元素应用一个函数,并将结果展平为一个数组。](#26.
flatMap:对数组中的每个元素应用一个函数,并将结果展平为一个数组。) - [27. `take` 和 `drop`:返回数组的前 `n` 个元素和去掉前 `n` 个元素后的剩余部分。](#27.
take和drop:返回数组的前n个元素和去掉前n个元素后的剩余部分。) - [28. `toArray`:将其他集合类型转换为数组。](#28.
toArray:将其他集合类型转换为数组。) - [29. `toSeq` 和 `toList`:将数组转换为 `Seq` 或 `List`。](#29.
toSeq和toList:将数组转换为Seq或List。) - [30. `copyToArray`:将数组的一部分复制到另一个数组中。](#30.
copyToArray:将数组的一部分复制到另一个数组中。)
- [1. `length`:获取数组的长度。](#1.
- [整理不易,列位还请多多支持呀🤣🤣🤣🤣点赞 收藏 关注~](#整理不易,列位还请多多支持呀🤣🤣🤣🤣点赞 收藏 关注~)
一、数组的定义
Scala中数组是一种可以存储固定数量相同类型元素的数据结构。

Scala提供了多种定义数组的方法,下面博主就总结一下常用的哈(够用啦~🤣🤣🤣)
1. new 关键字
scala
val arrayName = new Array[ElementType](size)
- 类型参数 :
ElementType指定数组中元素的类型,Int,String,Double等。 - 大小 :
size指定数组的长度------正整数。 - 默认值 :对于基本类型,数组元素会被初始化为该类型的默认值(如
Int的默认值是0,Boolean的默认值是false)。对于引用类型,数组元素会被初始化为null。

Demo:

2. Array 对象的 apply 方法
scala
val arrayName = Array(element1, element2, ..., elementN)
- 直接列出数组中的所有元素,用逗号分隔。
- 编译器会根据提供的元素自动推断数组的类型。

为什么看起来没有显式调用 apply 方法?
- 隐式调用
apply方法------代码更加简洁和易读,符合 Scala 的设计哲学。 - 许多 Scala 标准库中的类和对象都提供了类似的
apply方法------创建实例的语法一致。

这两段代码实际上是等价的。编译器会将 Array(1, 2, 3) 转换为 Array.apply(1, 2, 3)。
贴一下apply方法的源码,感兴趣的小伙伴可以看一下哈:

如果数组包含不同类型元素,Scala如何处理嘞?
Tips:🤣🤣🤣🤣
1. 类型提升
如果数组中的元素类型是数值类型(如 Int, Double, Float, Long 等),编译器会尝试将所有元素提升到一个共同的数值类型。
- 整数类型 :
Byte->Short->Int->Long - 浮点类型 :
Float->Double - 混合类型 :如果数组中既有整数类型又有浮点类型,所有整数类型会被提升为浮点类型。
Demo🤣🤣🤣🤣:

2. 找公共父类
如果数组中的元素类型不是数值类型,或者无法通过类型提升来统一类型,编译器会找到这些类型的最近公共父类。
- 基本类型和引用类型 :如果数组中既有基本类型又有引用类型,公共父类是
Any。 - 引用类型 :如果数组中的元素类型都是引用类型,编译器会找到这些类型的最近公共父类。

Demo🤣🤣🤣🤣:
数组中既有基本类型又有引用类型,公共父类是 Any。
数组中的元素类型都是引用类型,编译器会找到这些类型的最近公共父类。


3. 创建多维数组
scala
val arrayName = Array.ofDim[ElementType](dim1, dim2, ..., dimN)
or
var array_name = Array(Array(elements), Array(elements)
- 多维:可以创建一维、二维甚至更高维度的数组。
- 尺寸 :每个维度的大小由参数
dim1,dim2, ... 指定。 - 默认值:所有元素会被初始化为该类型的默认值。
Demo🤣🤣🤣🤣:


二、数组常用方法
家人们,方法太多啦,介绍一些常用的🤣🤣🤣
有些方法不仅仅是数组可以用奥,Scala中一些其他的集合(数组、列表、向量等)也可以使用!🤣🤣🤣

1. length:获取数组的长度。

2. apply:通过索引获取数组中的元素。
scala
val element = arr(index)
- 隐式调用
apply方法 :arr(0)是arr.apply(0)的语法糖(Syntactic Sugar)------对底层更复杂语法的一种简化表示。

- 显式调用
apply方法 :arr.apply(0)明确地调用了Array对象的apply方法。

3. update:通过索引更新数组中的元素。
scala
arr(index) = value

等价于:
scala
arr.update(index, value)
index:要更新的元素的索引。value:新的值。

- 隐式调用 :
arr(0) = 10是arr.update(0, 10)的语法糖(Syntactic Sugar)------对底层更复杂语法的一种简化表示。。 - 显式调用 :
arr.update(0, 10)明确地调用了Array对象的update方法。
4. foreach:遍历数组中的每个元素。
foreach:用于遍历数组中的每个元素,并对每个元素执行某个操作。

scala
array.foreach(f: (T) => Unit)
-
array:要遍历的数组。 -
f:一个函数,接受一个参数(数组中的元素),并返回Unit(相当于 Java 中的void)。 -
参数 :接受一个函数作为参数------如何处理每个元素。
-
返回值 :
foreach方法本身返回Unit,因为其主要用于执行带有"副作用"的操作(如打印、累加等)。
Demo🤣🤣🤣:
1. 带有操作的 foreach

2. 带有"副作用"的操作

3. 使用 foreach 进行过滤和打印

x => println(x)是一个匿名函数,接受一个参数x并打印它。arr.foreach(println)是简化的形式,直接将println作为函数传递给foreach。

5. map:对数组中的每个元素应用一个函数,并返回一个新的数组。
scala
val newArr = arr.map(f: (T) => U)
arr:原始数组。f:一个函数,接受一个参数(数组中的元素),并返回一个新的值。newArr:应用函数后的新数组。

1. 使用简化的匿名函数

在_ * 2 是一个简化的匿名函数,等价于 x => x * 2。
2. 复杂的映射操作

map 方法将数组中的每个字符串转换为大写。
3. 多参数映射操作
使用 map 方法处理元组:将每个元组的第一个元素乘以 2,并将第二个元素转换为大写。

4. 嵌套的 map 操作
使用嵌套的 map 方法来处理二维数组的每个子数组。

外层的 map 方法处理每个子数组,内层的 map 方法处理子数组中的每个元素。
6. filter:过滤数组中的元素,返回一个新的数组。
scala
val newArr = arr.filter(p: (T) => Boolean)
arr:原始数组。p:一个谓词函数(Predicate Function),接受一个参数(数组中的元素),并返回一个布尔值,表示该元素是否满足条件。newArr:包含满足条件的元素的新数组。
Demo:

1.使用简化的匿名函数
_ % 2 == 0 是 x => x % 2 == 0 的简写形式,更加简洁🤣🤣🤣。

2. 复杂的过滤条件
筛选出长度大于 5 的字符串,并返回一个新的数组:

3. 组合多个条件
筛选出大于 4 的偶数,并返回一个新的数组。

4. filterNot 方法
filterNot 方法与 filter 方法相反,返回不满足条件的元素。

7. foldLeft:从左到右累积数组中的元素。(fold、foldRight)
1.累计和

arr.foldLeft(0)((acc, x) => acc + x):0是初始值,表示累积结果的初始状态。(acc, x) => acc + x是一个匿名函数,接受两个参数:acc:累积结果,初始值为 0。x:当前元素,即数组中的每个元素。
- 函数体
acc + x表示将当前元素x加到累积结果acc上。

2. 计算乘积

arr.foldLeft(1)((acc, x) => acc * x):1是初始值,表示累积结果的初始状态。(acc, x) => acc * x是一个匿名函数,接受两个参数:acc:累积结果,初始值为 1。x:当前元素,即数组中的每个元素。
- 函数体
acc * x表示将当前元素x乘到累积结果acc上。

3. 字符串连接

arr.foldLeft("")((acc, x) => acc + x):""是初始值,表示累积结果的初始状态,这里是一个空字符串。(acc, x) => acc + x是一个匿名函数,接受两个参数:acc:累积结果,初始值为一个空字符串。x:当前元素,即数组中的每个字符串。
- 函数体
acc + x表示将当前字符串x连接到累积结果acc上。

Tips🤣🤣🤣:也可以使用其他名称来代替 acc 和 x,只要它们在函数体内有意义即可。

total:累积结果,初始值为 0。num:当前元素,数组中的每个元素。

result:累积结果,初始值为 1。num:当前元素,数组中的每个元素。

str:累积结果,初始值为一个空字符串。word:当前元素,数组中的每个字符串。
Tips:fold、foldRight用法同理哈
| 特性 | fold (一般) |
foldLeft |
foldRight |
|---|---|---|---|
| 方向 | 可能是并行的,不保证顺序 | 从左到右累积 | 从右到左累积 |
| 顺序保证 | 可能不保证顺序(并行时) | 保证从左到右的顺序 | 保证从右到左的顺序 |
| 初始值 | 需要初始值 | 需要初始值 | 需要初始值 |
| 常见用途 | 通用折叠操作(支持并行) | 保证顺序的累积操作 | 需要从右到左处理数据的场景 |
scala
val result = arr.fold(initialValue)(operation)
arr:原始数组。initialValue:累积的初始值。operation:一个二元操作符,接受两个参数(累积结果和当前元素),并返回一个新的累积



8. reduce:将数组中的元素减少为一个单一的值。
reduce 会自动选择列表中的第一个和第二个元素进行合并,再将结果与第三个元素进行合并,依此类推。

2. reduce 和上面咱们提到的 fold 的差不多哈🤣:
- 功能 :都用于对集合中的元素进行"折叠"操作 ,将集合的元素通过某种二元操作(如加法、乘法等)合并为一个单一的结果。
- 高阶函数 :两者都是高阶函数,需要一个二元函数作为参数,这个函数定义了如何合并两个元素。
- 返回类型 :返回类型是集合元素的类型,而不是某种通用的类型,比如
reduce和fold都返回与集合元素相同类型的结果。
3. fold 和 reduce 的区别:
| 特性 | reduce |
fold |
|---|---|---|
| 初始值 | 不需要初始值 | 需要一个初始值(可以是任意类型) |
| 空集合 | 对于空集合,reduce 会抛出异常 |
对于空集合,fold 会返回初始值 |
| 灵活性 | 只能使用集合中已有的元素类型进行操作 | 可以使用任何类型作为初始值(类型灵活) |
| 适用场景 | 用于确保集合中有元素的情况下,进行合并操作 | 用于需要初始化值的情况,尤其是处理空集合时 |
空集合的情况:
reduce:如果集合为空,reduce会抛出异常UnsupportedOperationException,因为它没有初始值来进行折叠。

fold:对于空集合,fold会返回你提供的初始值。

- 使用
reduce:当确定集合不为空,并且只需要根据元素类型进行折叠时,reduce更简洁。 - 使用
fold:当需要处理空集合或者想要指定初始值时,fold是更安全且灵活的选择。
9. mkString:将数组中的元素连接成一个字符串。
将集合中的元素转换为一个字符串,并可以选择在元素之间插入分隔符。
scala
val result = coll.mkString(sep: String)
coll:原始集合。sep:元素之间的分隔符。
Demo:
mkString 方法有多种重载形式:
- 无参数:将所有元素连接成一个字符串,没有分隔符。

- 一个参数:将所有元素连接成一个字符串,并在元素之间插入指定的分隔符。

- 三个参数:在结果字符串的开头和结尾添加指定的前缀和后缀,并在元素之间插入指定的分隔符。

mkString 方法适用于各种集合类型,如数组、列表、向量等。
1. 列表

2. 向量

3. 集合

10. sortWith:根据给定的比较函数对数组进行排序。
scala
val sortedArray = arr.sortWith(comparisonFunction)
arr:原始数组。comparisonFunction:一个布尔函数,接受两个参数(a和b),并返回一个布尔值。如果a应该排在b前面,则返回true,否则返回false。
话不多说 上 Demo🤣🤣🤣:
1. 升序排序整数数组

- 两个参数(
a和b),并返回一个布尔值。如果a应该排在b前面,则返回true,否则返回false。

2. 降序排序整数数组

- 两个参数(
a和b),并返回一个布尔值。如果a应该排在b前面,则返回true,否则返回false。

3. 按字符串长度排序

- 两个参数(
a和b),并返回一个布尔值。如果a应该排在b前面,则返回true,否则返回false。

4. 按对象属性排序

11. zip:将两个数组配对成一个元组数组。
zip ------将两个相同长度的数组组合成一个新的数组,其中每个元素都是一个元组,元组的第一个元素来自第一个数组,第二个元素来自第二个数组。
scala
val zippedArray = arr1.zip(arr2)
arr1:第一个数组。arr2:第二个数组。zippedArray:结果数组,其中每个元素是一个元组(arr1(i), arr2(i))。

Tips:不同长度的数组
如果两个数组的长度不同,zip 方法会以较短的数组为准,多余的元素会被忽略。

12. contains:检查数组是否包含某个元素。
contains ------检查数组是否包含某个特定的元素。
scala
val result = arr.contains(element)
arr:原始数组。element:要检查的元素。result:布尔值,表示数组是否包含指定的元素。



13. indexOf:查找数组中某个元素的第一个索引。
scala
val index = arr.indexOf(element)
arr:原始数组。element:要查找的元素。index:返回的索引值,如果找到元素则返回其索引,否则返回-1。



14. slice:提取数组的一个子数组。
scala
val subArray = arr.slice(start, end)
arr:原始数组。start:子数组的起始索引(包含)。end:子数组的结束索引(不包含)。subArray:返回的新数组,包含arr中从start到end - 1的元素。
Demo:



如果提供的索引超出了数组的范围,slice 方法会自动调整索引,确保不会抛出异常。

15. concat:连接两个数组。
scala
val concatenatedArray = Array.concat(arr1, arr2)
arr1:第一个数组。arr2:第二个数组。concatenatedArray:返回的新数组,包含arr1和arr2的所有元素。
1. 连接整数数组

2. 连接字符串数组

3. 连接多个数组

16. reverse:反转数组。
scala
val reversedArray = arr.reverse
arr:原始数组。reversedArray:返回的新数组,包含arr中元素的反向顺序。
1. 反转整数数组

2. 反转字符串数组

17. distinct:去除数组中的重复元素。
scala
val uniqueArray = arr.distinct
arr:原始数组。uniqueArray:返回的新数组,包含arr中的所有唯一元素。
1. 去除整数数组中的重复元素

2. 去除字符串数组中的重复元素

3. 去除对象数组中的重复元素

18. exists:检查数组中是否存在满足条件的元素。
scala
val result = arr.exists(predicate)
arr:原始数组。predicate:一个谓词函数,接受一个元素作为参数,并返回一个布尔值。result:布尔值,表示数组中是否存在至少一个元素满足predicate函数的条件。
1. 检查整数数组中是否存在偶数

2. 检查字符串数组中是否存在以 "a" 开头的字符串

3. 检查对象数组中是否存在年龄大于 30 的人

19. forall:检查数组中的所有元素是否都满足某个条件。
scala
val result = arr.forall(predicate)
arr:原始数组。predicate:一个谓词函数,接受一个元素作为参数,并返回一个布尔值。result:布尔值,表示数组中的所有元素是否都满足predicate函数的条件。
1. 检查整数数组中所有元素是否都小于 10

2. 检查字符串数组中所有元素是否都以 "a" 开头

3. 检查对象数组中所有人的年龄是否都大于 20

20. find:查找数组中第一个满足条件的元素,返回 Option 类型。
scala
val result: Option[Element] = arr.find(predicate)
arr:原始数组。predicate:一个谓词函数,接受一个元素作为参数,并返回一个布尔值。result:Option类型的结果,表示数组中第一个满足predicate函数条件的元素。如果找到了满足条件的元素,则返回Some(element),否则返回None。
1. 查找整数数组中第一个偶数

2. 查找字符串数组中第一个以 "a" 开头的字符串

3. 查找对象数组中第一个年龄大于 30 的人

21. count:计算数组中满足条件的元素的数量。
scala
val count = arr.count(predicate)
arr:原始数组。predicate:一个谓词函数,接受一个元素作为参数,并返回一个布尔值。count:整数,表示数组中满足predicate函数条件的元素的数量。
1. 计算整数数组中偶数的数量

2. 计算字符串数组中以 "a" 开头的字符串的数量

3. 计算对象数组中年龄大于 30 的人的数量

22. min 和 max:分别返回数组中的最小值和最大值。
scala
val minValue = arr.min
val maxValue = arr.max
arr:原始数组。minValue:数组中的最小值。maxValue:数组中的最大值。
1. 整数数组

2. 浮点数数组

3. 字符串数组(基于字典序)

23. sum 和 product:分别返回数组中所有元素的总和和乘积。
scala
val totalSum = arr.sum
val totalProduct = arr.product
arr:原始数组。totalSum:数组中所有元素的总和。totalProduct:数组中所有元素的乘积。

24. partition:将数组分为两个数组,一个包含满足条件的元素,另一个包含不满足条件的元素。
scala
val (satisfyingElements, nonSatisfyingElements) = arr.partition(predicate)
arr:原始数组。predicate:一个谓词函数,接受一个元素作为参数,并返回一个布尔值。satisfyingElements:包含满足predicate函数条件的元素的数组。nonSatisfyingElements:包含不满足predicate函数条件的元素的数组。
1. 分割整数数组

2. 分割字符串数组
,arr.partition(_.startsWith("a")) 将数组 arr 分为两个数组:startsWithA 包含所有以 "a" 开头的字符串,notStartsWithA 包含所有不以 "a" 开头的字符串。
3. 分割对象数组

people.partition(_.age > 30) 将数组 people 分为两个数组:olderThan30 包含所有年龄大于 或 等于30 的人,youngerOrEqual30 包含所有年龄小于 30 的人。
25. groupBy:根据某个条件将数组中的元素分组。
scala
val grouped = arr.groupBy(keyFunction)
arr:原始数组。keyFunction:一个函数,接受一个元素作为参数,并返回一个键(通常是某种类型的值)。grouped:一个映射(Map),键是分组的依据,值是属于该组的元素列表。
1. 根据整数的奇偶性分组

2. 根据字符串的首字母分组

3. 根据对象的属性分组

26. flatMap:对数组中的每个元素应用一个函数,并将结果展平为一个数组。
scala
val result = arr.flatMap(function)
arr:原始数组。function:一个函数,接受一个元素作为参数,并返回一个集合(如数组、列表等)。result:一个展平后的数组,包含所有应用函数后得到的元素。
1. 将每个字符串拆分为字符数组

2. 将每个整数乘以 2 并生成一个新的数组

27. take 和 drop:返回数组的前 n 个元素和去掉前 n 个元素后的剩余部分。
scala
val firstNElements = arr.take(n)
val remainingElements = arr.drop(n)
arr:原始数组。n:要取或去掉的元素数量。firstNElements:包含数组前n个元素的新数组。remainingElements:包含去掉前n个元素后的剩余部分的新数组。
1. 整数数组

2. 字符串数组

28. toArray:将其他集合类型转换为数组。
scala
val array = collection.toArray
collection:原始集合,可以是列表、集合、映射等。array:转换后的数组。
1. 列表转换为数组

2. 集合转换为数组

集合是无序的,所以输出的顺序可能与插入顺序不同。
3. 映射转换为数组

数组中的每个元素是一个元组,表示映射中的键值对。
29. toSeq 和 toList:将数组转换为 Seq 或 List。

30. copyToArray:将数组的一部分复制到另一个数组中。
scala
src.copyToArray(dest, destIndex, length)
src:源数组,从中复制元素。dest:目标数组,将元素复制到此数组中。destIndex:目标数组中的起始索引,从该索引开始复制元素。length:要复制的元素数量。

src.copyToArray(dest, 2, 5) 将源数组 src 的前 5 个元素复制到目标数组 dest 的索引 2 位置开始的位置。

src.copyToArray(dest, 0, 3) 将源数组 src 的前 3 个元素复制到目标数组 dest 的起始位置。
