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
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
scala> sc.parallelize(List(("a", 1), ("b", 2), ("c", 3), ("d", 4)), 2).count
res74: Long = 4
reduce
scala> sc.parallelize(List(6, 7, 8, 9, 10)).reduce(_+_)
res75: Int = 40
first & take
- def take(num: Int): Array[T]
- first
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)