Spark 常用算子

Spark的算子的分类

官网RDD操作指南 https://spark.apache.org/docs/latest/rdd-programming-guide.html#resilient-distributed-datasets-rdds

  • 从大方向来说,Spark 算子大致可以分为以下两类:

    1)Transformation 变换/转换算子:这种变换并不触发提交作业,完成作业中间过程处理。
    Transformation 操作是延迟计算的,也就是说从一个RDD 转换生成另一个 RDD 的转换操作不是马上执行,需要等到有 Action 操作的时候才会真正触发运算。
    2)Action行动算子:这类算子会触发 SparkContext 提交 Job 作业。
    Action 算子会触发 Spark 提交作业(Job),并将数据输出 Spark系统。

  • Spark 算子大致可以分为以下三类:

    1)Value数据类型的Transformation算子,这种变换并不触发提交作业,针对处理的数据项是Value型的数据。
    2)Key-Value数据类型的Transfromation算子,这种变换并不触发提交作业,针对处理的数据项是Key-Value型的数据对。

    3)Action算子,这类算子会触发SparkContext提交Job作业。

1)Value数据类型的Transformation算子

一、输入分区与输出分区一对一型

  • map(func) : 对原 RDD 中每个元素运用 func 函数,并生成新的 RDD
    在这里插入图片描述
val list = List(1,2,3)
sc.parallelize(list).map(_ * 10).foreach(println)

// 输出结果: 10 20 30 (这里为了节省篇幅去掉了换行,后文亦同)
  • flatMap(func) :与map类似,将原RDD中的每个元素通过函数f转换为新的元素,并将这些元素放入一个集合,构成新的RDD
  • 在这里插入图片描述
val list = List(List(1, 2), List(3), List(), List(4, 5))
sc.parallelize(list).flatMap(_.toList).map(_ * 10).foreach(println)

// 输出结果 : 10 20 30 40 50
  • mapPartitions(func) :mapPartitions是map的一个变种。map的输入函数应用于RDD中的每个元素,而mapPartitions的输入函数应用于每个分区,也就是把每个分区中的内容作为整体来处理的。
    在这里插入图片描述
val list = List(1, 2, 3, 4, 5, 6)
sc.parallelize(list, 3).mapPartitions(iterator => {
  val buffer = new ListBuffer[Int]
  while (iterator.hasNext) {
    buffer.append(iterator.next() * 100)
  }
  buffer.toIterator
}).foreach(println)
//输出结果
100 200 300 400 500 600
  • glom() :将每一个分区的元素合并成一个数组,形成新的 RDD 类型是RDD[Array[T]]
    在这里插入图片描述
var rdd1 = sc.parallelize(Array(10,20,30,40,50,60), 4)
rdd1.glom.collect
//输出结果
 Array(Array(10), Array(20, 30), Array(40), Array(50, 60))

二、输入分区与输出分区多对一型

  • union(otherDataset) :合并两个 RDD
    在这里插入图片描述
val list1 = List(1, 2, 3)
val list2 = List(4, 5, 6)
sc.parallelize(list1).union(sc.parallelize(list2)).foreach(println)
// 输出: 1 2 3 4 5 6
  • cartesian(otherDataset):计算 2 个 RDD 的笛卡尔积. 尽量避免使用
    在这里插入图片描述
val list1 = List("A", "B", "C")
val list2 = List(1, 2, 3)
sc.parallelize(list1).cartesian(sc.parallelize(list2)).foreach(println)

//输出笛卡尔积
(A,1)
(A,2)
(A,3)
(B,1)
(B,2)
(B,3)
(C,1)
(C,2)
(C,3)

三、输入分区与输出分区多对多型

  • groupBy(func):按照func的返回值进行分组.
    func返回值作为 key, 对应的值放入一个迭代器中. 返回的 RDD: RDD[(K, Iterable[T])
    在这里插入图片描述
//创建一个 RDD,按照元素的奇偶性进行分组
 val rdd1 = sc.makeRDD(Array(1, 3, 4, 20, 4, 5, 8))
 rdd1.groupBy(x => if(x % 2 == 1) "odd" else "even").collect
 //输出结果
 Array((even,CompactBuffer(4, 20, 4, 8)), (odd,CompactBuffer(1, 3, 5)))

四、输出分区为输入分区子集型

  • filter(func):map是对RDD中的每个元素都执行一个指定函数来产生一个新的RDD。任何原RDD中的元素在新RDD中都有且只有一个元素与之对应
    在这里插入图片描述
val list = List(3, 6, 9, 10, 12, 21)
sc.parallelize(list).filter(_ >= 10).foreach(println)

// 输出: 10 12 21
  • distinct([numTasks])):对 RDD 中元素执行去重操作. 参数表示任务的数量.默认值和分区数保持一致.
    在这里插入图片描述
  • subtract (otherDataset):计算差集. 从原 RDD 中减去 原 RDD 和 otherDataset 中的共同的部分
    在这里插入图片描述
val list = List(1, 2, 2, 4, 4)
sc.parallelize(list).distinct().foreach(println)
// 输出: 4 1 2
  • sample(withReplacement, fraction, seed):数据采样。有三个可选参数:设置是否放回 (withReplacement)、采样的百分比 (fraction)、随机数生成器的种子 (seed)
    在这里插入图片描述
// 每 个 方 框 是 一 个 RDD 分 区。 
//通 过 sample 函 数, 采 样 50% 的 数 据。
//V1、 V2、 U1、 U2、U3、U4 采样出数据 V1 和 U1、 U2 形成新的 RDD。

val list = List(1, 2, 3, 4, 5, 6)
sc.parallelize(list).sample(withReplacement = false, fraction = 0.5).foreach(println)

五、Cache型

  • cache() : cache 将 RDD 元素从磁盘缓存到内存。 相当于 persist(MEMORY_ONLY) 函数的功能。
     在这里插入图片描述

  • persist(newLevel:StorageLevel):persist 函数对 RDD 进行缓存操作。数据缓存在哪里依据 StorageLevel 这个枚举类型进行确定。 有以下几种类型的组合。, DISK 代表磁盘,MEMORY 代表内存, SER 代表数据是否进行序列化存储。

在这里插入图片描述
在这里插入图片描述

2)Key-Value数据类型的Transfromation算子

一、输入分区与输出分区一对一

  • mapValues():针对(K,V)形式的类型只对V进行操作
    在这里插入图片描述
val rdd = sc.parallelize(Array((1, "a"), (10, "b"), (11, "c"), (4, "d"), (20, "d"), (10, "e")))
rdd.mapValues("<" + _ + ">").collect
//计算结果
Array((1,<a>), (10,<b>), (11,<c>), (4,<d>), (20,<d>), (10,<e>))

二、对单个RDD或两个RDD聚集

单个RDD聚集
  • combineByKey[C]:与reduceByKey类似,相当于将元素(int, int)KV对变换为(int, Seq[int])新的KV对
    在这里插入图片描述
  • reduceByKey(func, [numTasks]) :在一个(K,V)的 RDD 上调用,返回一个(K,V)的 RDD,使用指定的reduce函数,将相同key的value聚合到一起,reduce任务的个数可以通过第二个可选的参数来设置。
    在这里插入图片描述
  • partitionBy(partitioner:Partitioner):对 pairRDD 进行分区操作,如果原有的 partionRDD 的分区器和传入的分区器相同, 则返回原 pairRDD,否则会生成 ShuffleRDD,即会产生 shuffle 过程。
    在这里插入图片描述
两个RDD聚集
  • cogroup(otherDataset, [numTasks]):在类型为(K,V)和(K,W)的 RDD 上调用,返回一个(K,(Iterable,Iterable))类型的 RDD
    在这里插入图片描述

三、连接

  • join(otherDataset, [numTasks]):内连接:在类型为(K,V)和(K,W)的 RDD 上调用,返回一个相同 key 对应的所有元素对在一起的(K,(V,W))的RDD

在这里插入图片描述

  • leftOutJoin rightOutJoin fullOuterJoin:LeftOutJoin(左外连接)和RightOutJoin(右外连接)相当于在join的基础上先判断一侧的RDD元素是否为空,如果为空,则填充为空。 如果不为空,则将数据进行连接运算,并返回结果。

3)Action算子

一、无输出

  • foreach(func):针对 RDD 中的每个元素都执行一次func,每个函数是在 Executor 上执行的, 不是在 driver 端执行的.
    在这里插入图片描述

二、HDFS

  • saveAsTextFile(path):将数据集的元素以textfile的形式保存到HDFS文件系统或者其他支持的文件系统,对于每个元素,Spark 将会调用toString方法,将它装换为文件中的文本
    在这里插入图片描述
  • saveAsObjectFile(path):用于将 RDD 中的元素序列化成对象,存储到文件中。
    在这里插入图片描述

三、Scala集合和数据类型

  • collect:以数组的形式返回 RDD 中的所有元素.所有的数据都会被拉到 driver 端, 所以要慎用
    在这里插入图片描述

  • collectAsMap:collectAsMap对(K,V)型的RDD数据返回一个单机HashMap。 对于重复K的RDD元素,后面的元素覆盖前面的元素。
    左侧方框代表RDD分区,右侧方框代表单机数组。 数据通过collectAsMap函数返回给Driver程序计算结果,结果以HashMap形式存储。
    在这里插入图片描述

  • reduceByKeyLocally:实现的是先reduce再collectAsMap的功能,先对RDD的整体进行reduce操作,然后再收集所有结果返回为一个HashMap。

  • lookup:Lookup函数对(Key,Value)型的RDD操作,返回指定Key对应的元素形成的Seq。 这个函数处理优化的部分在于,如果这个RDD包含分区器,则只会对应处理K所在的分区,然后返回由(K,V)形成的Seq。 如果RDD不包含分区器,则需要对全RDD元素进行暴力扫描处理,搜索指定K对应的元素。
    左侧方框代表RDD分区,右侧方框代表Seq,最后结果返回到Driver所在节点的应用中。
    在这里插入图片描述

  • count:count 返回整个 RDD 的元素个数。
    在这里插入图片描述

  • top(num:Int)(implicit ord:Ordering[T]):Array[T]:top可返回最大的k个元素。
    相近函数说明如下。

    ·top返回最大的k个元素。

    ·take返回最小的k个元素。

    ·takeOrdered返回最小的k个元素,并且在返回的数组中保持元素的顺序。

    ·first相当于top(1)返回整个RDD中的前k个元素,可以定义排序的方式Ordering[T]。

返回的是一个含前k个元素的数组。

  • reduce(func):通过func函数聚集 RDD 中的所有元素,先聚合分区内数据,再聚合分区间数据。
    在这里插入图片描述
  • fold:折叠操作,aggregate的简化操作,seqop和combop一样的时候,可以使用fold
    在这里插入图片描述
  • aggregate:aggregate函数将每个分区里面的元素通过seqOp和初始值进行聚合,然后用combine函数将每个分区的结果和初始值(zeroValue)进行combine操作。这个函数最终返回的类型不需要和RDD中元素类型一致。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值