Spark Core 中的 Action 操作

Spark中的Action算子在遇到时才启动作业执行。本文详细介绍了不同类型的Action操作,如collect(可能导致Driver端OOM)、saveAsTextFile、foreach与foreachPartition、count、reduce、first与take、top与takeOrdered、countByKey以及collectAsMap的功能和应用场景。
摘要由CSDN通过智能技术生成

Action算子的特点

  • 只有遇到 Action 算子才会提交作业开始执行
  • 代码中都会有 sc.runJob(xxx)

Action 算子操作

collect

  • 返回一个包含 RDD 中所有元素的数组
  • collect 会把所有数据收集到 Driver 端,所以如果数据量很大会报 OOM 异常
scala> sc.parallelize(List(6, 7, 8, 9, 10)).collect
res64: Array[Int] = Array(6, 7, 8, 9, 10)

saveAsTextFile

  • 将 RDD 的内容输出到文件系统
scala> sc.parallelize(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)), 2).saveAsTextFile("file:home/hadoop/data/rddout")

[hadoop@hadoop004 rddout]$ ll
total 8
-rw-r--r-- 1 hadoop hadoop 12 Oct 27 22:05 part-00000
-rw-r--r-- 1 hadoop hadoop 12 Oct 27 22:05 part-00001
-rw-r--r-- 1 hadoop hadoop  0 Oct 27 22:05 _SUCCESS
[hadoop@hadoop004 rddout]$ cat part-00000
(a,1)
(b,2)
[hadoop@hadoop004 rddout]$ cat part-00001
(c,3)
(d,4)

scala> sc.textFile("file:home/hadoop/data/rddout").collect
res71: Array[String] = Array((a,1), (b,2), (c,3), (d,4))

foreach & foreachPartition

  • foreach 对于 RDD 中每个元素执行传入的函数,foreachPartition 对于RDD 中每个分区执行传入的函数
  • 一个使用foreach输出的问题
scala> sc.parallelize(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)), 2).sortBy(_._2, false).foreach(println)
(d,4)
(c,3)
(b,2)
(a,1)

scala> sc.parallelize(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)), 2).sortBy(_._2, false).foreach(println)
(b,2)
(a,1)
(d,4)
(c,3)

Q:为什么输出结果有时会不一样?sortBy是分区内有序还是全局有序?

试着写入到文件然后再读取看看结果

scala> sc.parallelize(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)), 2).sortBy(_._2, false).saveAsTextFile("file:home/hadoop/data/out")

scala> sc.textFile("file:home/hadoop/data/out").collect
res73: Array[String] = Array((d,4), (c,3), (b,2), (a,1))

可以看出sortBy是全局有序的,只是因为不能确定多分区情况下哪一个task先执行完成,所以输出结果有时会不同

count

  • 返回 RDD 中的元素个数
scala> sc.parallelize(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)), 2).count
res74: Long = 4

reduce

  • RDD 中的元素两两进行操作
scala> sc.parallelize(List(6, 7, 8, 9, 10)).reduce(_+_)
res75: Int = 40

first & take

  • def take(num: Int): Array[T]
    • 按照原顺序取前 num 个元素
  • first
    • 取第一个元素,底层调用的是 take(1)

top & takeOrdered

  • takeOrdered:按照 Ordering 的排序规则升序排序,然后取前 num 个
def takeOrdered(num: Int)(implicit ord: Ordering[T])
  • top:按照 Ordering 的排序规则降序排序,然后取前 num 个。底层调用的就是 takeOrdered
def top(num: Int)(implicit ord: Ordering[T]): Array[T] = withScope {
  takeOrdered(num)(ord.reverse)
}

countByKey

  • 对 KV 类型的 RDD 中的每个 key 进行计数,返回一个 Map[K, Long]
# 源码实现
def countByKey(): Map[K, Long] = self.withScope {
    self.mapValues(_ => 1L).reduceByKey(_ + _).collect().toMap
  }

scala> rdd1.zipWithIndex().countByKey()
res3: scala.collection.Map[Int,Long] = Map(10 -> 1, 20 -> 1, 6 -> 1, 9 -> 1, 8 -> 1, 15 -> 1)

collectAsMap

  • 将 KV 类型的 RDD 输出为 Map 类型的集合
scala> rdd1.zipWithIndex().collectAsMap()
res2: scala.collection.Map[Int,Long] = Map(8 -> 2, 20 -> 4, 10 -> 1, 9 -> 3, 15 -> 5, 6 -> 0)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值