scala combineByKey用法说明

语法是:

combineByKey[C](  
  createCombiner: V => C,  
  mergeValue: (C, V) => C,  
  mergeCombiners: (C, C) => C
) 

标记一下:(因为有很多同样的字母,方便说明我就按照字母+数字标记一下)


语法说明:(不复制网上的,我按照我的理解大白话说明)

  • 1.combineByKey 中的byKey 就是按照键来处理,你就默认 他丫知道 哪些键是一样的,他会在每个分区自动归类同样的键,你就操心怎么处理值就行了, 总之就是:对相同K,把V合并成一个集合

  • 2.每条数据会被遍历,如果某条数据的键 是第一遇到,就用createCombiner 处理,否则用mergeValue (你要是第一次去银行存钱,流程就是先开户, 下一次去了你存钱就是其他的流程了->直接存钱就行)

  • 3.createCombiner 和 mergeValue 处理单个分区中数据, mergeCombiners是每个分区处理完了 合并数据使用

例子说明:Fred 和 william 二个人 数语外分数 分别是
val scores = Array(("Fred", 88), ("Fred", 95), ("Fred", 91), ("Wilma", 93), ("Wilma", 95), ("Wilma", 98))

求他们各自的平均成绩

思路是: 通过combineByKey函数把按照人分组 求出 他们的总分 和科目数 ,然后用map函数 除一下就完事

操作1:为了模拟多个分区 我创建2个分区




说明:参照语法图



首先:各个分区的兄弟们先干活

第一个分区遍历开始: 数据为

--> 处理(Fred,88), 因为是第一次遇到键“Fred”, 所以调用createCombiner方法 (v)=> (v,1) ; 这里就是(88) => (88,1)

--> 处理(Fred,95),不是第一次遇到键“Fred”,调用mergeValue方法(acc:(Int,Int),v)=>(acc._1+v,acc._2+1),: 这里就是((88,1),95)=>(88+95, 1+1)

--> 处理(Fred,91),不是第一次遇到键“Fred”,调用mergeValue方法(acc:(Int,Int),v)=>(acc._1+v,acc._2+1),: 这里就是((88+95,1+1),91)=>(88+95+91, 1+1+1)

第一个分区遍历结束:返回(274,3) (注意一个分区中可能有很多不一样的键值对,我这里碰巧只有fred一个人 ,也许还有张三(), 李四())(程序本来就按照键BYkeys分组了,所以不用担心混淆了键)

第二个分区遍历开始: 数据为:

--> 处理(Wilma,93), 因为是第一次遇到键“Fred”, 所以调用createCombiner方法 (v)=> (v,1) ; 这里就是(93) => (93,1)

--> 处理(Wilma,95),不是第一次遇到键“Fred”,调用mergeValue方法(acc:(Int,Int),v)=>(acc._1+v,acc._2+1),: 这里就是((93,1),95)=>(93+95, 1+1)

--> 处理(Wilma,98),不是第一次遇到键“Fred”,调用mergeValue方法(acc:(Int,Int),v)=>(acc._1+v,acc._2+1),: 这里就是((93+95,1+1),98)=>(93+95+98, 1+1+1)

第一个分区遍历结束:返回(286,3)

然后:各个分区兄弟干完了 汇总处理

由于我的数据少,没有模拟到比如分区 1 和分区2 都有 Fred的成绩, 他三科成绩在第一个分区就全部统计到了。

假如 分区一返回的是fred信息(274,3),

分区二返回是 fred的体育成绩(80,1), 和wilma的三科成绩(286,3)

汇总后开始调用mergeCombiners: (C, C) => C 方法

       (acc1:(Int,Int),acc2:(Int,Int))=>(acc1._1+acc2._1,acc1._2+acc2._2)) 执行到就应该是((274,3),(80,1)) =>(274+80 , 3+1) (fred的结果)

。。。。。。。。。。。。=>(286,3) (WILMA的结果)

操作3: 把分数总和 和 科目数量除一下 得到平均成绩

你可能感兴趣的:(scala combineByKey用法说明)