spark的combineByKey算子原理详解

val rdd1 = sc.makeRDD(Array(("A", 1), ("A", 2), ("B", 3), ("B", 1), ("B", 2), ("C", 1)), 2)
val rdd2 = rdd1.combineByKey(
      (v: Int) => v +"_",
      (c: String, v:Int) => c + "@" + v,
      (c1: String, c2: String) => c1 + "$" +c2
    )
    println(rdd2.collect().toBuffer)
结果:ArrayBuffer((B,3_$1_@2), (A,1_@2), (C,1_))

详解

算子的三个参数的用法:

第一个参数,如果分区中元素的key是第一次出现,那么就使用第一个参数应用到这个元素中,如果遇到的元素经过了第一个参数的处理,那么就让第二个参数应用到已存在的元素和这个元素上,第三个参数是将所有分区的计算结果按照key进行汇总分组计算

算子的计算过程:

注:因为sc.makeRDD的时候指定了一个参数2,所以会在两个分区中进行计算,所以下面的分析过程也是在两个分区的基础上

(1)分析以A为key的元素:

  1. 元素("A", 1)在第一个分区中的key是第一次出现所以被第一个参数应用得到=>("A", 1_);
  2. ("A", 2)的key出现过一次并且被第一个参数应用过,所以使用第二个参数应用到("A", 1_)和("A", 2)上得到=> (A,1_@2);
  3. 然后以A为key的元素没有在其它分区中出现过了所以key为A的计算结果就是:(A,1_@2);

(2)分析以B为key的元素:

  1. 元素("B", 3)在第一个分区中的key是第一次出现所以被第一个参数应用得到=>("B", 3_);
  2. 以B为key的元素在第一个分区中已经没有,但是第二个分区中存在,("B", 1)以B为key第一次出现,得到=>("B", 1_)
  3. ("B", 2)在是以B为key第二个分区中出现过并且被第一个参数应用过,因此使用第二个参数应用已存在的和新加入的得到=>(B, 1_@2)
  4. 第一个分区得到的是("B", 3_),第二个分区得到的是(B, 1_@2),然后用第三个参数应用到这两个结果中(汇总分组统计),至于顺序问题就看哪个分区先计算完成,这里是第一个分区先计算完成因此得到=>(B, 3_$1_@2)

(3)分析以C为key的元素:

  1. 以C为key的元素只在第二个分区中出现过,因此只会被第一个参数所应用得到(C,1_)即是以C为key的计算结果

小结

本文详细解释了combineByKey的工作原理,这个过程是围绕着combineByKey的三个参数展开的,第一个参数只会处理key第一次出现的元素,第二个参数处理出现过的key的元素(将新加入的key和之前处理过的key进行处理),第三个参数是将每个分区的结果进行汇总然后分组再处理。

你可能感兴趣的:(spark,笔记)