Spark核心编程(RDD转换算子)之聚合算子

本文详细介绍了Spark中的聚合算子,包括reduceByKey、groupByKey、aggregateByKey、foldByKey和combineByKey,强调了它们的区别和底层实现。重点讨论了预聚合和无预聚合的算子,以及如何根据业务需求选择合适的聚合操作。
摘要由CSDN通过智能技术生成

RDD转换算子 之 聚合算子

  • 聚合算子可以说是Spark计算里面的核心,所以搞懂底层的实现很有必要。

reduceByKey

说明
  • 可以将数据按照相同的key对value进行聚合
    在这里插入图片描述
  /**
   * 使用一个关联与交换的reduce函数来合并每个key的values值。
   * 在将结果发送到reducer之前,这也将在每个mapper上本地执行合并,类似于MapReduce中的combiner。
   */
  def reduceByKey(partitioner: Partitioner, func: (V, V) => V): RDD[(K, V)] = self.withScope {
    // 不会对第一个value进行处理,分区内和分区间计算规则相同
    combineByKeyWithClassTag[V]((v: V) => v, func, func, partitioner)
  }

  /**
   * 输出将使用numPartitions分区,进行哈希分区。
   */
  def reduceByKey(func: (V, V) => V, numPartitions: Int): RDD[(K, V)] = self.withScope {
    reduceByKey(new HashPartitioner(numPartitions), func)
  }

  /**
   * 输出将使用现有的分区器或是并行级别来进行哈希分区。
   */
  def reduceByKey(func: (V, V) => V): RDD[(K, V)] = self.withScope {
    reduceByKey(defaultPartitioner(self), func)
  }
案例
def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("partition by")
    val sc = new SparkContext(conf)

    val rdd: RDD[(String, Int)] = sc.makeRDD(
      List(
        ("a", 1), ("b", 2),
        ("c", 3), ("d", 4),
        ("a", 5), ("b", 6)
      )
    )

    // 使用现有的分区器或是并行级别来进行哈希分区
    val rdd1: RDD[(String, Int)] = rdd.reduceByKey(_ + _)
    println(rdd1.collect().mkString(", "))

    // 使用numPartitions分区,进行哈希分区
    val rdd2: RDD[(String, Int)] = rdd.reduceByKey(_ + _, 2)
    println(rdd2.collect().mkString(", "))

    // 使用指定分区器进行分区
    val rdd3: RDD[(String, Int)] = rdd.reduceByKey(new HashPartitioner(2), _ + _)
    println(rdd3.collect().mkString(", "))
}

reduceByKey进一步调用:

reduceByKey(partitioner: Partitioner, func: (V, V) => V): RDD[(K, V)]
-- combineByKeyWithClassTag[V]((v: V) => v, func, func, partitioner)

查看combineByKeyWithClassTag方法:
/**
   * 泛型函数,使用一组自定义的聚合函数,来组合每个key的元素。将RDD[(K, V)]转换为RDD[(K, C)]类型的结果,得到一个“组合类型”C。
   * 
   * 用户提供三个函数:
   * - `createCombiner`, 将V转换为C(比如,创建只有一个元素的list)// 将计算的第一个值转换结构
   * - `mergeValue`, 将V合并成C(比如,将它添加到list的末尾)// 分区内的计算规则
   * - `mergeCombiners`, 将两个C组合成一个 // 分区间的计算规则
   * 
   * 此外,用户可以控制输出RDD的分区,以及是否执行map端的聚合(如果一个mapper可以使用同一个键生成多个项)
   * 
   * 注意:V和C可以不同 -- 例如,可以将类型(Int, Int)的RDD分组为类型(Int, Seq[Int])的RDD
   */
def combineByKeyWithClassTag[C](
              createCombiner: V => C, // 将计算的第一个值转换结构
              mergeValue: (C, V) => C, // 分区内的计算规则
              mergeCombiners: (C, C) => C, // 分区间的计算规则
              partitioner: Partitioner, // 控制输出RDD的分区
              mapSideCombine: Boolean = true, // 是否执行map端的聚合
              serializer: Serializer = null)(implicit ct: ClassTag[C]): RDD[(K, C)] = self.withScope {
    require(mergeCombiners != null, "mergeCombiners must be defined") // required as of Spark 0.9.0
    if (keyClass.isArray) {
      if (mapSideCombine) {
        throw new SparkException("Cannot use map-side combining with array keys.")
      }
      if (partitioner.isInstanceOf[HashPartitioner]) {
        throw new SparkException("HashPartitioner cannot partition array keys.")
      }
    }
    val aggregator = new Aggregator[K, V, C](
      self.context.clean(createCombiner),
      self.context.clean(mergeValue),
      self.context.clean(mergeCombiners))
    if (self.
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spark RDD(弹性分布式数据集)是Spark中最基本的数据抽象,它代表了一个不可变、可分区、可并行计算的数据集合。转换算子是用于对RDD进行转换操作的方法,可以通过转换算子RDD进行各种操作和变换,生成新的RDD。 以下是一些常见的Spark RDD转换算子: 1. map(func):对RDD中的每个元素应用给定的函数,返回一个新的RDD,新RDD中的每个元素都是原RDD中元素经过函数处理后的结果。 2. filter(func):对RDD中的每个元素应用给定的函数,返回一个新的RDD,新RDD中只包含满足条件的元素。 3. flatMap(func):对RDD中的每个元素应用给定的函数,返回一个新的RDD,新RDD中的每个元素都是原RDD中元素经过函数处理后生成的多个结果。 4. union(other):返回一个包含原RDD和另一个RDD中所有元素的新RDD。 5. distinct():返回一个去重后的新RDD,其中不包含重复的元素。 6. groupByKey():对键值对RDD进行分组,返回一个新的键值对RDD,其中每个键关联一个由具有相同键的所有值组成的迭代器。 7. reduceByKey(func):对键值对RDD中具有相同键的值进行聚合操作,返回一个新的键值对RDD,其中每个键关联一个经过聚合函数处理后的值。 8. sortByKey():对键值对RDD中的键进行排序,返回一个新的键值对RDD,按照键的升序排列。 9. join(other):对两个键值对RDD进行连接操作,返回一个新的键值对RDD,其中包含两个RDD中具有相同键的所有元素。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值