reduceByKey、groupByKey和combineByKey的详解
明明可以靠容貌吃饭,为何自己非要靠才华,没办法,优秀的人就是这么偏执
话不多说直接上代码
大家一定要有耐心 关于combineByKey一定要耐心看输出的注解
造测试数据,将该数组封装成RDD,基于该数据分析三个算子的用法
Array((1, 1), (1, 2), (2, 2), (2, 3))
package com.knowlegene.kw.test
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object Test02 {
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("CreateGraph")
val sc = new SparkContext(conf)
sc.setLogLevel("WARN")
//测试数据
val rdd: RDD[(Int, Int)] = sc.parallelize(Array((1, 1), (1, 2), (2, 2), (2, 3)))
println("reduceByKey---")
rdd.reduceByKey((a, b) => a + b).foreach(println(_))
/**
* 输出结果:
* (1,3)
(2,5)
*/
println("groupByKey---")
rdd.groupByKey().foreach(println(_))
rdd.groupByKey().map(x => (x._1, x._2.sum)).foreach(println(_))
/**
* 输出结果:
* (1,CompactBuffer(1, 2))
(2,CompactBuffer(2, 3))
(1,3)
(2,5)
*/
println("combineBykey---")
rdd.values.foreach(println(_))
/**
* 2
2
1
3
*/
rdd.combineByKey(
a=>(1,a), //a 类似于rdd中每个元素的value值 对应上边就是 1 2 3 4 (类似与初始化)
(a:(Int,Int),v)=>(a._1+1,a._2+v), //a 相当于上一步的a v相当于同意分区内相同key的value值 1 2 3 4
(c1:(Int,Int),c2:(Int,Int))=>(c1._1+c2._1,c1._2+c2._2) //分区间合并
).foreach(println(_))
/**
* 输出结果
* (1,(2,3)) 1 出现了两次 出现的和为3
(2,(2,5)) 2 出现了两次 出现的和为5
*/
}
}
reduceByKey:
用于对每个key对应的多个value进行merge操作,最重要的是它能够在本地先进行merge操作,并且merge操作可以通过函数自定义;
groupByKey:
combineByKey:
以实现一个计算平均值的功能为例来分别说明createCombiner、mergeValue和mergeCombiners三个函数的作用和定义方法。
##A createCombiner(value)
createCombiner: V => C ,这个函数把当前rdd中的值(value)作为参数,此时我们可以对其做些附加操作(类型转换)并把它返回 (这一步类似于初始化操作,分区内操作)
def createCombiner(value):
(value, 1)
##B mergeValue(acc, value)
mergeValue: (C, V) => C,该函数把元素V合并到之前的元
(createCombiner)上 (每个分区内合并)
def mergeValue(acc, value):
# 注意,这里的acc即为createCombiner产生的C。
# 这里,用acc[0]表明为acc这个元组中的第一个元素,在scala中acc._1表示
(acc[0]+value, acc[1]+1)
###C mergeCombiners: (acc1, acc2)
mergeCombiners: (C, C) => C,该函数把2个元素C合并 (此函数作用范围在rdd的不同分区间内,跨分区合并)
def mergeCombiners(acc1, acc2):
# 注意,到这一步,表明这个rdd的每条数据都已经被###A和###B捕获匹配完毕
(acc1[0]+acc2[0], acc1[1]+acc2[1])
如果大街上看见三个人在打你老板,
你会去帮忙吗……?
不去,没必要,
三个人就够了……!