Spark快速上手(6)Spark核心编程-RDD行动算子Action

RDD(3)

RDD行动算子

所谓行动算子,就是触发Job执行的方法

reduce

函数签名
def reduce(f: (T, T) => T): T
函数说明
聚集RDD中的所有元素,先聚合分区内数据,再聚合分区间数据
e.g.
code:

def main(args: Array[String]): Unit = {
    val source: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    //    聚合数据
    val reduceResult: Int = source.reduce(_ + _)
    println(reduceResult)
  }

result:
10

collect

函数签名
def collect(): Array[T]
函数说明
在驱动程序中,以数组Array形式返回数据集中的所有元素
e.g.
code:

@Test
    def testCollect(): Unit = {
      //    收集数据到driver
      source.collect().foreach(println)
    }

count

函数签名
def count(): Long
函数说明
返回RDD中的元素的个数
e.g.
code:

 @Test
    def testCount(): Unit = {
      //    返回 RDD 中元素的个数
      println(source.count())
    }

first

函数签名
def first(): T
函数说明
返回RDD中的第一个元素
e.g.
code:

@Test
    def testFirst(): Unit ={
      //    返回 RDD 中的第一个元素
      println(source.first())
    }

take

函数签名
def take(num: Int): Array[T]
函数说明
返回一个由 RDD 的前 n 个元素组成的数组
e.g.
code:

 @Test
    def testTake(): Unit = {
      //    返回一个由RDD前n个元素组成的数组
      println(source.take(2).mkString(","))
    }

takeOrdered

函数签名
def takeOrdered(num: Int)(implicit ord: Ordering[T]): Array[T]
函数说明
返回该RDD排序后的前n个元素组成的数组
e.g.
code:

@Test
    def testTakeOrdered(): Unit = {
      //    返回一个由RDD前n个元素排序后组成的数组
      source.takeOrdered(2).foreach(println)
    }

aggregate

函数签名
def aggregate[U: ClassTag](zeroValue: U)(seqOp: (U, T) => U, combOp: (U, U) => U): U
函数说明
分区的数据通过初始值和分区内的数据进行聚合,然后再和初始值进行分区间的数据聚合
e.g.
code:

@Test
    def testAggregate(): Unit = {
      //     将该 RDD 所有元素相加得到结果
      //val result: Int = rdd.aggregate(0)(_ + _, _ + _)
      println(source1.aggregate(10)(_ + _, _ + _))
    }

note:
这里的结果 如果按照aggregateByKey算子运算会是30,但是使用aggregate算子运算是40,这是因为aggregateByKey中的初始
值智慧参与一次分区内的运算,而aggregate会参加分区内的运算后,还会参加分区间的运算

fold

函数签名
def fold(zeroValue: T)(op: (T, T) => T): T
函数说明
折叠操作,aggregate的简化版操作

@Test
    def testFold(): Unit = {
      //      折叠操作,aggregate的简化版操作
      println(source1.fold(0)(_ + _))
    }

countByKey&countByValue

函数签名
def countByKey(): Map[K, Long] = self.withScope { self.mapValues(_ => 1L).reduceByKey(_ + _).collect().toMap }

def countByValue()(implicit ord: Ordering[T] = null): Map[T, Long] = withScope { map(value => (value, null)).countByKey() }
函数说明
统计每种key/value的个数
val source1: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4), 2)
val source2: RDD[(Int, String)] = sc.makeRDD(List((1, "a"), (2, "a"), (1, "a"), (3, "c")))

@Test
    def testCountByKey_CountByValue(): Unit = {
      //      统计每种 value 的个数
      println(source1.countByValue())
      //      统计每种 key 的个数
      println(source2.countByKey())
    }

save相关算子

函数签名

def saveAsTextFile(path: String): Unit
def saveAsObjectFile(path: String): Unit
def saveAsSequenceFile(path: String,codec: Option[Class[_ <: CompressionCodec]] = None): Unit

函数说明
将数据保存到不同格式的文件中

@Test
    def testSave(): Unit ={
      // 保存成 Text 文件
      source2.saveAsTextFile("output/testSaveAsTextFile")
      // 序列化成对象保存到文件
      source2.saveAsObjectFile("output/testSaveAsObjectFile")
      // 保存成 SequenceFile 文件
      source1.map((_,1)).saveAsSequenceFile("output/testSaveAsSequenceFile")
    }

note:
saveAsSequenceFile() 方法要求数据必须为 K-V 键值对类型

foreach

函数签名

def foreach(f: T => Unit): Unit = withScope {
	val cleanF = sc.clean(f)
	sc.runJob(this, (iter: Iterator[T]) => iter.foreach(cleanF))
}

函数说明
分布式遍历RDD中的每一个元素,调用指定函数;是Driver端内存集合的循环遍历集合方法

@Test
    def testForeach(): Unit = {
      //收集后打印
      source.collect().foreach(println)
      //分布式打印
      source.foreach(println)
    }

note:
①使用collect算子,是先将数据按照分区进行采集,然后进行打印输出,这是在Driver端内存中的输出;
而直接使用foreach算子,实际上是在Executor端分布式打印 输出,并不是按照顺序采集再打印输出的。
由于Driver和Executor是两个不同的结构,RDD 的方法外部的操作都是在Driver端执行的,而方法内部的逻辑代码是在Executor端执行的,以在进行数据传输之前需要先对类序列化操作样例类case class XX 在编译过程中会自动序列化,所以这也是主动继承序列化类以外的一种方法。
e.g.
code:

val source: RDD[Int] = sc.makeRDD(List(2, 1, 3, 4))

 def main(args: Array[String]): Unit = {
    val user = new test()
    val user1 = new User()

    println()
    source.foreach(num => {
      print("age:" + (user.age + num)+" ")
      println("age:" + (user1.age + num)+",")
    })

    sc.stop()

  }

  case class User(){
    val age: Int =30
  }


  class test extends Serializable {
    val age: Int = 30

result:

age:31 age:31,
age:32 age:32,
age:34 age:34,
age:33 age:33,
posted @ 2022-07-08 07:53  Unknown尚可  阅读(68)  评论(0编辑  收藏  举报