Scala 第二篇 算子篇
Scala 第二篇 算子篇
一、数组方法
1、数组的遍历
1 |
|
2、数组获取元素
获取首尾元素
1
2
3
4
5
6
7
8
9
10
11
12val buffer = ArrayBuffer(1, 2, 3, 4)
val head = buffer.head // 第一个元素
val opt1 = buffer.headOption // 第一个元素
val tail = buffer.tail // 除第一个元素以外的其他元素
// 剩余元素(阶梯) 4(1,2,3,4),3(2,3,4),2(3,4),1(4),0()
val tails: Iterator[ArrayBuffer[Int]] = buffer.tails
val last = buffer.last // 最后一个元素
val opt2 = buffer.lastOption // 最后一个元素
val init = buffer.init // 除最后一个元素以外的其他元素
val inits = buffer.inits // 剩余元素(阶梯) 4(1,2,3,4),3(1,2,3),2(1,2),1(1),0()获取满足条件连续长度和元素
1
2
3
4
5
6val size1 = buffer.prefixLength(e => e < 3) // 从集合的开头满足条件元素数量
val size2 = buffer.segmentLength(e => e > 1, 1) //从 from 下标的连续满足条件元素数量
val buf1 = buffer.take(1) // 从集合的开头开始获取指定数量的元素。
val buf2 = buffer.takeRight(2) // 从集合的末尾开始获取指定数量的元素。
val buf3 = buffer.takeWhile(e => e < 3) // 从集合的开头开始获取连续满足条件的元素。
3、数组排序
sorted
,sortBy
,sortWith
1
2
3
4
5
6
7
8
9
10
11
12val buffer = ArrayBuffer((5, 2), (2, 5), (3, 2), (2, 4))
val sort1 = buffer.sorted // 默认按第一个值升序,如果第一个值相等按第二个值升序,如果有第三个值同理
val sort2 = buffer.sortBy(_._2) // 指定排序值,按第二个值排序(默认升序)
// sortWith 定义元素之间的比较规则
// 如果第一个值不相等按第一个值降序,否则按第二个值降序
val sort3 = buffer.sortWith((a, b) => (
if(a._1 != b._1) a._1 > b._1
else a._2 > b._2
))隐式函数 (不建议)
1
2
3val buffer = ArrayBuffer((5, 2), (2, 5), (3, 2), (2, 4))
implicit val orderingTp2: Ordering[(Int, Int)] = Ordering.by(_._2) // 按第二个值
val sort5 = buffer.sorted // 按第二个值升序
4、交集,并集,补集
1 |
|
输出:
1 |
|
补充:
1 |
|
5、集合转换操作
一个维度的转变
1
2
3
4
5
6
7
8
9import scala.collection.mutable.ArrayBuffer
val buffer = ArrayBuffer(1, 2, 3, 4, 5)
// 正向差异类型转变,(将数字x映射为x*2并转化为字符串)
val doubledBuffer: ArrayBuffer[String] = buffer.map(x => (x * 2).toString)
// 正向同类型转变
val squaredBuffer: ArrayBuffer[Int] = buffer.transform(x => x * x)
// 逆向转变
val reversedSquaredBuffer: ArrayBuffer[Int] = buffer.reverseMap(x => x * x)二维变换
1
2
3
4
5
6
7
8
9
10
11
12
13import scala.collection.mutable.ArrayBuffer
val buffer2D = ArrayBuffer(
ArrayBuffer(1, 2, 3),
ArrayBuffer(4, 5, 6),
ArrayBuffer(7, 8, 9)
)
// 使用 flatMap 将二维转换为一维,并对值做映射 (*2)
val flatBuffer: ArrayBuffer[Int] = buffer2D.flatMap(_.map(_ * 2))
// 使用 flatten 将二维转换为一维
val flattenedBuffer: ArrayBuffer[Int] = buffer2D.flatten
// 使用 transpose 进行二维数组缓冲区转置
val transpose: ArrayBuffer[ArrayBuffer[Int]] = buffer2D.transpose类型变换
1
2
3
4
5
6
7
8
9
10
11import scala.collection.mutable
import scala.collection.parallel.mutable.ParArray
val buffer = mutable.Buffer(1, 2, 2, 3, 4, 5)
val buffer_tp2 = mutable.Buffer((1, "a"), (2, "b"), (3, "c"))
val mutableBuffer: mutable.Buffer[Int] = buffer.toBuffer // 转换为可变的,为了增删
val array: Array[Int] = buffer.toArray // 转换为数组,(下标,排序)
val parArray: ParArray[Int] = buffer.toParArray // 转换为并行数组,分布式计算
val map: Map[Int, String] = buffer_tp2.toMap // 转换为 Map,键值映射
val set: Set[Int] = buffer.toSet // 转换为集合(去重)
6、合并,拆解,填充
1 |
|
输出:
1 |
|
7、分组,排列
1 |
|
二、算子
1、简单计算
数组元素为数值类型可以直接计算
1
2
3
4
5
6import scala.collection.mutable.ArrayBuffer
val buffer = ArrayBuffer(1, 2, 3, 4, 5)
val sum = buffer.sum
val max = buffer.max
val min = buffer.min
val pro = buffer.product // 阶乘非数值元素类型
1
2
3
4
5val buffer = ArrayBuffer(("aaa", 3), ("bbb", 1), ("ccc", 2), ("aaa", 2))
val sum = buffer2.map(e => e._2).sum
val max: (String, Int) = buffer2.maxBy(e => e._2)
val min: (String, Int) = buffer2.minBy(e => e._2)
val cnt = buffer2.count(e => e._2 < 2)计算优化:并行序列,并行计算
并行数组
ParArray[T]
,它是一个并行版本的数组,允许在多个线程上并行地操作数组元素。这对于对大型数据集进行处理或利用多核处理器进行并行计算非常有用,可以提高处理效率。1
val par: ParArray[T] = buffer.par
2、高阶计算
简介
- 聚合操作:
aggregate
方法对数组进行聚合操作,指定一个初始值o: O
,一个用于映射元素的函数map: (O, T) => O
,和一个用于合并两个结果的函数red: (O, O) => O
。这个操作会将数组元素映射为结果。在并行计算中使用这个操作,直接调用并行数组的par.aggregate
方法。- 折叠操作:
fold
方法对数组进行折叠,指定一个初始值init: O
,和一个用于合并两个结果的函数func: (O, O) => O
。这个操作会从数组的一端开始,逐个将元素与初始值进行合并,直到折叠到另一端。通过指定Left
或Right
来指定折叠的方向。- 扫描操作:
scan
方法对数组进行扫描,指定一个初始值init: O
,和一个用于合并两个结果的函数f: (O, O) => O
。这个操作会从数组的一端开始,逐个将元素与初始值进行合并,并在每一步生成一个过程结果。最终结果是一个包含所有过程结果的数组缓冲区。- 归约操作:
reduce
方法对数组进行归约操作,指定一个用于合并两个结果的函数f: (O, O) => O
。这个操作会从数组的一端开始,逐个将元素进行合并,直到最终只剩下一个结果为止。通过指定Left
或Right
来指定归约的方向。
1
2
3
4
5
6
7
8
9// 聚合操作
val rst:O = buffer.aggregate(o:O)(map:(O,T)=>O,red:(O,O)=>O)
val rst:O = par.aggregate(o:O)(map:(O,T)=>O,red:(O,O)=>O) // 并行 Map & Red
// 双向折叠操作
val rst:O = buffer.fold[Left|Right](init:O)(func:(O,O)=>O)
// 过程结果扫描操作
val rst:ArrayBuffer[O] = buffer.scan[Left|Right](init:O)(f:(O,O)=>O)
// 归约操作
val rst:O = buffer.reduce[Left|Right](f:(O,O)=>O)案例
1、
aggregate
案例1
2
3
4
5
6
7
8
9
10
11val buffer = ArrayBuffer(1, 2, 3, 4)
val map = (a:Int,b:Int) => {
println(s"MAP $a + $b = ${a+b}")
a + b
}
val reduce = (a:Int,b:Int) => {
println(s"RED $a + $b = ${a+b}")
a + b
}
val rst: Int = buffer.par.aggregate(0)(map,reduce)输出:
1
2
3
4
5
6
7MAP 0 + 2 = 2
MAP 0 + 1 = 1
MAP 0 + 4 = 4
MAP 0 + 3 = 3
RED 1 + 2 = 3
RED 3 + 4 = 7
RED 3 + 7 = 102、
fold
案例1
2
3
4
5
6
7
8val buffer = ArrayBuffer(1, 2, 3)
val add = (a:Int, b:Int) => {
println(s"$a + $b = ${a+b}")
a + b
}
val rst: Int = buffer.fold(0)(add)
println("-------------------------")
val rst: Int = buffer.foldRight(0)(add)输出:
1
2
3
4
5
6
70 + 1 = 1
1 + 2 = 3
3 + 3 = 6
-------------------------
3 + 0 = 3
2 + 3 = 5
1 + 5 = 63、
scan
案例1
2
3
4
5
6
7
8
9
10val buffer = ArrayBuffer(1, 2, 3, 4)
val add = (a: Int, b: Int) => {
println(s"$a + $b = ${a + b}")
a + b
}
val rst1: ArrayBuffer[Int] = buffer.scan(0)(add)
println(rst1)
val rst2: ArrayBuffer[Int] = buffer.scanRight(0)(add)
println(rst2)输出:
1
2
3
4
5
6
7
8
9
100 + 1 = 1
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
ArrayBuffer(0, 1, 3, 6, 10)
4 + 0 = 4
3 + 4 = 7
2 + 7 = 9
1 + 9 = 10
ArrayBuffer(10, 9, 7, 4, 0)4、
reduce
案例1
2
3
4
5
6
7
8val buffer = ArrayBuffer(1, 2, 3, 4)
val add = (a: Int, b: Int) => {
println(s"$a + $b = ${a + b}")
a + b
}
val rst1: Int = buffer.reduce(add)
println("-------------------------")
val rst2: Int = buffer.reduceRight(add)输出:
1
2
3
4
5
6
71 + 2 = 3
3 + 3 = 6
6 + 4 = 10
-------------------------
3 + 4 = 7
2 + 7 = 9
1 + 9 = 10简单优化
sizeHint(size: Int)
:这个重载形式接收一个整数参数size
,表示预期添加的元素数量。调用这个方法后,缓冲区的实现可能会调整内部数据结构的大小以适应更大的元素数量,从而提高性能。这对于在添加大量元素之前知道预期大小的情况很有用。sizeHint(data: TraversableLike[T])
:这个重载形式接收一个TraversableLike[T]
类型的参数data
,表示另一个集合,它的大小可以作为预期添加的元素数量的提示。调用这个方法后,缓冲区的实现可能会根据给定集合的大小来调整内部数据结构的大小,以适应更大的元素数量。sizeHintBounded(size: Int, data: TraversableLike[T])
:这个重载形式接收两个参数:一个整数size
和一个TraversableLike[T]
类型的参数data
。它表示给定集合的大小和另一个预期添加的元素数量。调用这个方法后,缓冲区的实现可能会根据这两个参数来调整内部数据结构的大小,以适应更大的元素数量。
1
2
3
4// 给出预期添加元素数量的提示,用于优化构建器的性能
buffer.sizeHint(size:Int)
buffer.sizeHint(data:TraversableLike[T])
buffer.sizeHintBounded(size:int,data:TraversableLike[T])
Scala 第二篇 算子篇
https://leaf-domain.gitee.io/2024/03/30/bigdata/scala/scala02/