Spark2.1.1<通俗易懂理解combineByKey-combineByKeyWithClassTag>
来源:互联网 发布:怎么设置linux的ip地址 编辑:程序博客网 时间:2024/06/01 07:43
combineByKey是Spark中一个比较核心的高级函数, groupByKey,reduceByKey的底层都是使用combineByKey实现的,这是我要弄清楚它的原因
1.6.0版的函数名更新为combineByKeyWithClassTag
combineByKey会调用combineByKeyWithClassTag,源码
def combineByKey[C]( createCombiner: V => C, mergeValue: (C, V) => C, mergeCombiners: (C, C) => C): RDD[(K, C)] = self.withScope { combineByKeyWithClassTag(createCombiner, mergeValue, mergeCombiners)(null) }
所以弄清楚combineByKey就能弄懂后者了
2.首先我们来看一例子
我有三类书
,每一本数都有一个价格,我们现在的任务是要把所有的书籍都卖出去,假设我们要为每一类书籍都买一个钱包来装这些书籍卖出去的价格
思路就是,当我们卖掉每一类书籍的第一本书的时候,将得到的钱去买一个钱包,然后其他同类书籍卖掉的钱直接装进钱包就好了,下面是代码实现
case class Book(val name: String, val price: Int) { //卖书然后买一个十块钱的钱包来装钱 def sellBook_buyWallet: Wallet = Wallet(price - 10)}case class Wallet(var money: Int) { //将不同的钱包的钱累加起来 def addMoney(that: Book): Wallet = Wallet(money + that.price)}object BookCombineByKey { def main(args: Array[String]): Unit = { val sparkconf = new SparkConf().setAppName("Book_Sell").setMaster("local") val sc = new SparkContext(sparkconf) val bookRDD = sc.makeRDD(Array( ("数据结构", Book("大话数据结构", 50)), ("数据结构", Book("数据结构C++版本", 80)), ("数据结构", Book("数据结构Java版本", 50)), ("算法", Book("算法导论", 50)), ("算法", Book("算法基础", 20)), ("算法", Book("算法心得", 50)), ("操作系统", Book("深入理解操作系统", 30)), ("操作系统", Book("Linux操作系统", 70)), ("操作系统", Book("Windows操作系统", 50)) )) println(bookRDD.partitions.size+"===================") val aggresult = bookRDD.combineByKeyWithClassTag( (book: Book) => book.sellBook_buyWallet, (w: Wallet, b: Book) => w.addMoney(b), (w1: Wallet, w2: Wallet) => { println("================ call ===============") Wallet(w1.money + w2.money) } ).collectAsMap().foreach(println) }}
其余的代码相当简单我就不讲解了,主要讲解combineByKey的参数,
- 第一个参数是说
(book: Book) => book.sellBook_buyWallet
满足了我们的需求,同类第一本书籍卖掉的时候,将得到的钱去买一个钱包,然后将卖书得到的钱减掉买钱包的钱,然后装入钱包。 - 第二个参数
(w: Wallet, b: Book) => w.addMoney(b)
满足我们的第二个需求,同类其他书籍卖掉得到的钱直接装入本类对应的钱包
第三个参数我们姑且不看,先将程序跑起来
看看执行结果:
算法类对应的钱包的钱数怎么来的?:
第一本书50元,卖掉得到50块钱,然后再买一个钱包,花了十块钱,现在还有50-10=40元,装进钱包,算法类第二本书卖掉得到20块钱,装进钱包,第三本买到得到50装进钱包,现在这个钱包有多少钱?50-10+20+50
以此类推,操作系统的钱怎么来的?
30-10+70+50=140
数据结构的钱?
50-10+80+50=170
这是不是很像,reduceBykey?
3.接下来我们来讲解第三个参数
(w1: Wallet, w2: Wallet)
你可以看到我在这个函数,里打印了一句话,但是控制台并没有输出这句话?
println("================ call ===============")
日志过长,我就不粘贴进来了
这是为什么呢?原来只有当同类的事物在不同的分区的时候,这个函数才会被触发。这在我们这个例子上对应的是什么呢?
这个就是,不同的地区的都同时在卖这些书籍,每一个地区都有三个不同的钱包,当所有的书籍都卖完了之后,我们再将这些钱包依次合并为三个大的钱包。并入地区一的数据结构的钱包转了1000块,地区二的数据结构的钱包装了500块,最终数据结构这个大钱包装了1500块。
那我们怎么样才能在上面的例子中触发这个函数呢?
在上面的代码运行时候的控制台中,我打印出了这个RDD的分区数目,可以看到只有一个分区
现在对代码做一点点修改,我创建RDD的时候,指定分区的数量是2,这以为这这些Book对象会分布到不同的分区上
看一下控制台:
可以看到现在的第三个函数的结果也被调用了
对比一下结果,我们第一次得到的结果是:
(算法,Wallet(110))(操作系统,Wallet(140))(数据结构,Wallet(170))
修改代码之后得到的结果是:
(算法,Wallet(100))(操作系统,Wallet(140))(数据结构,Wallet(170))
这是为什么?因为分区将算法类的书籍都分到了两个分区,操作系统和数据结构的所有书籍都在同一个分区
类似这样,算法类在两个分区分别都买了一个钱包,所以最终算法类有
50-10+20-10+50=100
其余两类没有变化。
- Spark2.1.1<通俗易懂理解combineByKey-combineByKeyWithClassTag>
- combineByKey
- svm通俗易懂的理解
- svm通俗易懂的理解
- 通俗易懂的理解卷积
- 数据库范式理解-通俗易懂
- pyspark中combineByKey的两种理解方法
- 通俗易懂的USB协议理解
- 遗传算法理解(通俗易懂)
- 通俗易懂SpringMVC整体框架理解
- 通俗易懂SpringMVC整体框架理解
- 通俗易懂SpringMVC整体框架理解
- 通俗易懂SpringMVC整体框架理解
- 【中间件】-通俗易懂的理解方式
- 通俗易懂的傅立叶级数理解
- 通俗易懂SpringMVC整体框架理解
- 通俗易懂的js原型理解
- Spark2.1.1Idea配置
- 最新调通的海思HI3519v101开发板【媲美原厂】求围观
- Nginx反向代理和负载均衡部署指南
- 我安装了最新版的phpstudy,用composer提示PHP版本低
- Lisp 调用 API 函数示例
- mysql 5.7首次登录设置密码
- Spark2.1.1<通俗易懂理解combineByKey-combineByKeyWithClassTag>
- 【Java并发编程】之六:Runnable和Thread实现多线程的区别(含代码)
- GDSOI2017 中学生数据结构题(Lct练习)
- 斯坦福机器学习-第三周(分类,逻辑回归,过度拟合及解决方法)
- QT中QLabel类的openExternalLinks和linkActivated使用时的一些注意细节
- dubbo
- 高通MSM8909 CAMERA TUNING 基础
- 架构设计:负载均衡层设计方案(7)——LVS + Keepalived + Nginx安装及配置
- 进程间通信IPC、LPC、RPC