combineBykey关键是要明白里面的三个函数:
  1. 当某个key第一次出现的时候,走的是第一个函数(createCombin);A function that creates a combiner. In the aggregateByKey function the first argument was simply an initial zero value. In combineByKey we provide a function that will accept our current value as a parameter and return our new value that will be merged with addtional values.
  2. 当某个keyN次出现(N > 1)的时候,将会走第二个函数;The second function is a merging function that takes a value and merges/combines it into the previously collecte value(s).
  3. 第三个函数是发生shuffle的时候,数据汇总的处理;处理逻辑一般和第二个函数一致;两个参数是来自于两个区的待累计处理参数。The third function combines the merged values together. Basically this function takes the new values produced at the partition level and combines them until we end up with one singular value.

  突然来看这个combineByKey有些唐突,不过你要明白combine含义就是合并,可能会好理解.combinebyKey很多时候会和map做接续,combine数据后,在map对于数据进行二次处理,比如下面的例子里面的求平均值;combineByKey做得是累加,当需要对累加值做后续处理的时候,map就出场了;另外,combinByKey其实可以写成mapValues+reduceByKey;mapValues + reduceByKey是两轮便利,combineByKey其实是一轮便利(不算第三个函数)。但是两者只是类似,却不相同;
  1.mapValues: 当一个遍历每个元素的时候,处理,参数是当前待处理元素;
  2.reduceByKey,是遍历一遍之后,第二遍遍历处理,一般是做累计逻辑处理,第一个参数就是历史累计值,第二个参数是当前待处理元素;
  代码如下:

 object Main {
def main(args: Array[String]) {
val scores = List(
ScoreDetail("xiaoming", "Math", 98),
ScoreDetail("xiaoming", "English", 88),
ScoreDetail("wangwu", "Math", 75),
ScoreDetail("wangwu", "English", 78),
ScoreDetail("lihua", "Math", 90),
ScoreDetail("lihua", "English", 80),
ScoreDetail("zhangsan", "Math", 91),
ScoreDetail("zhangsan", "English", 80)) var sparkConf = new SparkConf
//sparkConf.setMaster("yarn-client")
sparkConf.setAppName("app")
var sc = new SparkContext(sparkConf)
//val scoresWithKey = for( i<-scores) yield (i.studentName, i)
val scoresWithKey = scores.map(score => (score.studentName, score))
var scoresWithKeyRDD = sc.parallelize(scoresWithKey).partitionBy(new HashPartitioner(3)).cache
scoresWithKeyRDD.foreachPartition(partition => {
//println("***** partion.length: " + partition.size + "************")
while (partition.hasNext) {
val score = partition.next();
println("name: " + score._1 + "; id: " + score._2.score)
}
}) val avg = scoresWithKeyRDD.combineByKey(
(x: ScoreDetail) => {
println("score:" + x.score + "name: " + x.studentName)
(x.score, 1)},
(acc: (Float, Int), x: ScoreDetail) =>{
println("second ground:" + x.score + "name: " + x.studentName)
(acc._1 + x.score, acc._2 + 1)
},
(acc1: (Float, Int), acc2: (Float, Int)) => (acc1._1 + acc2._1, acc1._2 + acc2._2)
).map({ case (key, value) => (key, value._1 / value._2) })
/*
val avg = scoresWithKeyRDD.mapValues(value => (value.score, 1))
.reduceByKey((acc, item) => (acc._1 + item._1, acc._2 + item._2))
//.map(item => (item, item._2._1 / item._2._2)
.map({ case (key, value) => (key, value._1 / value._2) })
*/
avg.collect.foreach(println)
scoresWithKeyRDD.unpersist(true)
}
}

  combineByKey的处理逻辑通过日志可以看到:

   score:.0name: xiaoming
  second ground:.0name: xiaoming
  score:.0name: lihua
  second ground:.0name: lihua
  score:.0name: zhangsan
  second ground:.0name: zhangsan

  每个key只是走一次第一个函数;当同一个key第n次出现(n > 1)的时候,将会走第二个函数;这个和mapValues将会过遍历一遍,keyByValues再过一遍的逻辑还是不同的。

  combineByKey的一个老对手是groupbyKey,这个说法其实不准确,reduceByKey才是groupByKey的老对手;因为无论是reduceByKey还是groupByKey,其实底层都是调用combinByKey;但是groupByKey将会导致大量的shuffle,因为groupByKey的实现逻辑是将各个分区的数据原封不动的shuffle到reduce机器,由reduce机器进行合并处理,见下图:

  reduceByKey则是先将各个分区的数据进行合并(计算)处理后在shuffle到reducer机器;这样严重的减轻了数据传输的量。

Spark的CombineByKey的更多相关文章

  1. Spark入门(六)--Spark的combineByKey、sortBykey

    spark的combineByKey combineByKey的特点 combineByKey的强大之处,在于提供了三个函数操作来操作一个函数.第一个函数,是对元数据处理,从而获得一个键值对.第二个函 ...

  2. Spark 的combineByKey函数

    在Spark中有许多聚类操作是基于combineByKey的,例如group那个家族的操作等.所以combineByKey这个函数也是比较重要,所以下午花了点时间看来下这个函数.也参考了http:// ...

  3. Spark RDD——combineByKey

    为什么单独讲解combineByKey? 因为combineByKey是Spark中一个比较核心的高级函数,其他一些高阶键值对函数底层都是用它实现的.诸如 groupByKey,reduceByKey ...

  4. spark之combineByKey

    combineByKey def combineByKey[C](createCombiner: (V) => C, mergeValue: (C, V) => C, mergeCombi ...

  5. Spark实战系列目录

    1 Spark rdd -- action函数详解与实战 2 Spark rdd -- transformations函数详解与实战(上) 3 Spark rdd -- transformations ...

  6. Spark入门(七)--Spark的intersection、subtract、union和distinc

    Spark的intersection intersection顾名思义,他是指交叉的.当两个RDD进行intersection后,将保留两者共有的.因此对于RDD1.intersection(RDD2 ...

  7. Job 逻辑执行图

    General logical plan 典型的 Job 逻辑执行图如上所示,经过下面四个步骤可以得到最终执行结果: 从数据源(可以是本地 file,内存数据结构, HDFS,HBase 等)读取数据 ...

  8. Spark API 之 combineByKey(一)

    1       前言 combineByKey是使用Spark无法避免的一个方法,总会在有意或无意,直接或间接的调用到它.从它的字面上就可以知道,它有聚合的作用,对于这点不想做过多的解释,原因很简单, ...

  9. spark算子:combineByKey

    假设我们有一组个人信息,我们针对人的性别进行分组统计,并进行统计每个分组中的记录数. scala> val people = List(("male", "Mobi ...

随机推荐

  1. IOS-涂鸦

    // // PaintView.m // IOS_0224_涂鸦 // // Created by ma c on 16/2/24. // Copyright © 2016年 博文科技. All ri ...

  2. Day34 设计模式

    参考博客: http://www.cnblogs.com/alex3714/articles/5760582.html 什么是设计模式 Christopher Alexander:“每一个模式描述了一 ...

  3. 安装使用babel-polyfill。让IE支持es6

    安装 npm install --save-dev babel-polyfill 使用 在你的代码头部加载babel-polyfill,注意一定要在你的代码开始前,第一个js文件的顶部.如果是vue在 ...

  4. 关于Mac上使用ideviceinstaller操作iPhoneXR等24位UDID设备报“ERROR: Invalid UDID specified”解决办法

    最近新申请了一台iPhone XR, 测试时发现使用ideviceinstaller命令老是报错: Jackeys-MacBook-Pro:~ jackey$ ideviceinstaller -u ...

  5. zoj 2976 Light Bulbs(暴力枚举)

    Light Bulbs Time Limit: 2 Seconds      Memory Limit: 65536 KB Wildleopard had fallen in love with hi ...

  6. PHP 中使用explode()函数切割字符串为数组

    explode()函数的作用:使用一个字符串分割另一个字符串,打散为数组. 例如: 字符串 $pizza = "第1 第2 第3 第4 第5 第6"; 根据空格分割后:$piece ...

  7. Cassandra cqlsh - connection refused

    启动cqlsh时,保存如下: Connection error: ('Unable to connect to any servers', {'127.0.0.1': error(111, " ...

  8. Alpha冲刺(2/10)

    前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/9960487.html 作业博客:https://edu.cnblogs.com/campus/ ...

  9. Linux之VIM常用功能

    介绍:vim包含三种模式分别为 命令模式:浏览文件,临时更改vim的工作方式,对字符批量处理(也可进行配置) 插入模式:对文件内容进行编辑 退出模式:退出VIM操作 一.命令模式     1.调整vi ...

  10. linux 下 iscsi的简单使用

      一.准备工作 1.1.(服务端和客户端都需要设置) 系统使用的是CentOS6.8 禁用防火墙: 查看状态:# service iptables status 停止:# systemctl sto ...