键值对转换算子--最重要的算子combineByKey

  • 定义:combineByKey(createCombiner,mergePart,mergerbine )
combineByKey需要传递三个参数(函数)
1、createCombiner函数    将相同key值的某一个value数据进行一个函数操作,得到一个新的value数据---零值(新的value数据是我们后期聚合的数据)
      v=>U
2、mergepart函数       将同一个分区中key值相同的value数据(上一步函数中转换得到的新的value) 聚合操作
      (U,V)=>U
3、mergercombin函数    将不同分区中key值相同的聚合出来的结果再进行一次聚合操作
      (U,U)=>U
  • 解释:
解释 区别
reduce 对所有的数据进行聚合 数据类型无法定义
aggregateByKey 可以实现每个分区先聚合,然后再整体聚合 效率高,但是每一个分区聚合或者不同分区聚合的时候都必须和零值进行聚合
combineBykey 可以实现每个分区先聚合,然后再整体聚合 效率高,且不需要传递零值,到底对什么样的数据进行聚合,自定义
  • 案例:
object CombineByKeyTransRDD {
  def main(args: Array[String]): Unit = {
    val sparkConf = new SparkConf().setMaster("local").setAppName("kv")
    val sc = new SparkContext(sparkConf)

    combineByKeyOpt(sc)

    sc.stop()
  }

  def combineByKeyOpt(sc: SparkContext): Unit = {
    println("----------------combineByKey开始------------------")
    val rdd: RDD[(String,Int)] = sc.makeRDD(Array(("zs",60),("zs",70),("zs",80),("ls",66),("ls",60),("ls",77)))
    // 案例一:计算每一个学生的总分
    val sum: RDD[(String, Int)] = rdd.combineByKey(
      (a: Int) => {
        a
      },
      (a: Int, b: Int) => {
        a + b
      },
      (a: Int, b: Int) => {
        a + b
      }
    )
    /*
        (ls,203)
        (zs,210)
     */
    sum.foreach(println(_))

    // 案例二:计算平均分
    val value = rdd.combineByKey(
      // (60, 1)
      (a: Int) => {
        (a, 1)
      },
      // 70 (60, 1) => (130, 2) 80 => (210, 3)
      (tuple2: (Int, Int), score: Int) => {
        (tuple2._1 + score, tuple2._2 + 1)
      },
      (tuplea: (Int, Int), tupleb: (Int, Int)) => {
        (tuplea._1 + tupleb._1, tuplea._2 + tupleb._2)
      }
    )
    value.foreach(println(_)) // (ls,(203,3))   (zs,(210,3))
    val rdd4 = value.mapValues(tuple2 => {
      tuple2._1 / tuple2._2.toDouble
    })
    rdd4.foreach(println(_)) // (ls,67.66666666666667)   (zs,70.0)

    println("----------------combineByKey结束------------------")
  }
}
posted @ 2022-08-24 14:41  jsqup  阅读(29)  评论(0编辑  收藏  举报