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
的起始位置。