Spark—常用的RDD行动算子

Spark—常用的RDD行动算子

在RDD的创建一文中 >> Spark—RDD的创建(Local环境),讲到RDD在Yarn模式的工作原理时提到了算子的简单介绍,在这里会稍作原理性的补充。



一、算子?

算子 : Operator(操作)

  1. RDD的方法和Scala集合对象的方法不一样
  2. 集合对象的方法都是在同一个节点的内存中完成的。
  3. RDD的方法可以将计算逻辑发送到Executor端(分布式节点)执行为了区分不同的处理效果,所以将RDD的方法称之为算子。
  4. RDD的方法外部的操作都是在Driver端执行的,而方法内部的逻辑代码是在Executor端执行。

二、行动算子

常用转换算子可以戳这里 >> Spark—常用的RDD转换算子

1. reduce

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

代码如下(示例):

val sparkConf = new SparkConf().setMaster("local[*]").setAppName("Operator")
val sc = new SparkContext(sparkConf)

val rdd = sc.makeRDD(List(1,2,3,4))

// reduce
// result: 10
val reduceRes: Int = rdd.reduce(_+_)
println(reduceRes)

2. collect

  1. 函数签名

    def collect(): Array[T] = withScope {
    	val results = sc.runJob(this, (iter: Iterator[T]) => iter.toArray)
    	Array.concat(results: _*)
     }
    
  2. 函数说明
    在驱动程序中,以数组 Array 的形式返回数据集的所有元素
    代码如下(示例):

// collect : 方法会将不同分区的数据按照分区顺序采集到Driver端内存中,形成数组
// result: 1,2,3,4
val rdd = sc.makeRDD(List(1,2,3,4))
val collect: Array[Int] = rdd.collect()
println(collect.mkString(","))

3. count

  1. 函数签名

    /**
    * Return the number of elements in the RDD.
    */
     def count(): Long = sc.runJob(this, Utils.getIteratorSize _).sum
    
  2. 函数说明
    返回 RDD 中元素的个数

// count : 数据源中数据的个数
// result: 4
val rdd = sc.makeRDD(List(1,2,3,4))
val cnt = rdd.count()
println(cnt)

4. first

  1. 函数签名

     /**
    * Return the first element in this RDD.
    */
      def first(): T = withScope {
        take(1) match {
          case Array(t) => t
          case _ => throw new UnsupportedOperationException("empty collection")
        }
      }
    
  2. 函数说明
    返回 RDD 中的第一个元素

// first : 获取数据源中数据的第一个
// result: 1
val rdd = sc.makeRDD(List(1,2,3,4))
val first = rdd.first()
println(first)

5. take

  1. 函数签名

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

// take : 获取N个数据
// result: 1,2,3
val rdd = sc.makeRDD(List(1,2,3,4))
val takeRes: Array[Int] = rdd.take(3)
println(takeRes.mkString(","))

6. takeOrdered

  1. 函数签名

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

// takeOrdered : 数据排序后,取N个数据
// result: 1,2,3
val rdd1 = sc.makeRDD(List(4,2,3,1))
val takeOrdered: Array[Int] = rdd1.takeOrdered(3)
println(takeOrdered.mkString(","))

7. aggregate

  1. 函数签名

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

val sparkConf = new SparkConf().setMaster("local[*]").setAppName("Operator")
val sc = new SparkContext(sparkConf)

val rdd = sc.makeRDD(List(1,2,3,4),2)
// aggregate : 初始值会参与分区内计算,并且和参与分区间计算
//10 + [10 + (1+2)] + [10 + (3+4)]= 40
val result = rdd.aggregate(10)(_+_, _+_)
println(result)

sc.stop()

8. fold

  1. 函数签名

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

// 分区内与分区间的运算相同,可以简化
val result1 = rdd.fold(10)(_+_)
println(result1)

9. countByKey & countByValue

  1. 函数签名

    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()
      }
    
  2. 函数说明
    countByKey : 统计每种 key 的个数, 元素必须是k-v类型
    countByValue: 统计元素的个数

val sparkConf = new SparkConf().setMaster("local[*]").setAppName("Operator")
val sc = new SparkContext(sparkConf)

val rdd = sc.makeRDD(List(1,1,1,4),2)
val rdd1 = sc.makeRDD(List(
    ("a", 1),("a", 2),("a", 3),("b", 3)
))

// TODO - 行动算子
val intToLong: collection.Map[Int, Long] = rdd.countByValue()
println(intToLong)
val stringToLong: collection.Map[String, Long] = rdd1.countByKey()
println(stringToLong)

/*
result:
	Map(4 -> 1, 1 -> 3)
	Map(b -> 1, a -> 3)
*/

sc.stop()

10. save 相关算子

  1. 函数签名

    def saveAsTextFile(path: String): Unit
    def saveAsObjectFile(path: String): Unit
    def saveAsSequenceFile(
     path: String,
     codec: Option[Class[_ <: CompressionCodec]] = None): Unit
    
  2. 函数说明
    将数据保存到不同格式的文件中

val sparkConf = new SparkConf().setMaster("local[*]").setAppName("Operator")
val sc = new SparkContext(sparkConf)

val rdd = sc.makeRDD(List(1,1,1,4),2)
val rdd1 = sc.makeRDD(List(
    ("a", 1),("a", 2),("a", 3)
))

// TODO - 行动算子
// 普通文件
rdd.saveAsTextFile("output")
// 对象文件
rdd1.saveAsObjectFile("output1")
// saveAsSequenceFile方法要求数据的格式必须为K-V类型
// 序列文件
rdd1.saveAsSequenceFile("output2")

sc.stop()

11. foreach

  1. 函数签名

    def foreach(f: T => Unit): Unit = withScope {
     val cleanF = sc.clean(f)
     sc.runJob(this, (iter: Iterator[T]) => iter.foreach(cleanF))
    }
    
  2. 函数说明
    分布式遍历 RDD 中的每一个元素,调用指定函数

val sparkConf = new SparkConf().setMaster("local[*]").setAppName("Operator")
val sc = new SparkContext(sparkConf)

val rdd = sc.makeRDD(List(1,2,3,4))

// foreach 其实是Driver端内存集合的循环遍历方法
// 先用collect采集后打印,返回的是一个Array,属于scala的集合对象,集合对象的方法都是在同一个节点的内存中完成的。
rdd.collect().foreach(data => print(data+"\t"))
println()
println("******************")
// RDD的方法可以将计算逻辑发送到Executor端(分布式节点)执行
// foreach 其实是Executor端内存数据打印,
// RDD的方法外部的操作都是在Driver端执行的,而方法内部的逻辑代码是在Executor端执行。
// 分布式打印
rdd.foreach(data => print(data+"\t"))

/*
result:
	1	2	3	4	
	******************
	3	4	1	2
*/

sc.stop()

总结

文章也是仅作知识点的记录,欢迎大家指出错误,一起探讨~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值