spark combineByKey的使用

方法的定义:

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

1、作用:对相同 key,把valueList合并成一个值。比较像reduceByKey,但还是有区别的。

2、原理

每个分区的相同key有多个value,其中每个key的第一个value会使用createCombiner创建一个新的值newValue。

然后相同key的除第一个value之外的其他value都与newValue使用mergeValue再合并为一个newValue。

最终同一个分区,每个key的多个value会合并为一个newValue。

 

其他代码类比:

可以用其他代码来自己封装一个CombineByKey。。下面只是根据原理写的。。方便理解,但真实的不是这样实现的。

    implicit class Custom[K:ClassTag, V:ClassTag](rdd: RDD[(K, V)]) {

            def myCombineByKey[newV](createCombiner: V => newV, mergeValue: (newV, V) => newV, mergeCombiners: (newV, newV) => newV)(implicit kt: ClassTag[newV]): RDD[(K, newV)] = {

                //每个分区的相同key有多个value,其中每个key的第一个value会使用createCombiner创建一个新的值newValue。
                //然后相同key的除第一个value之外的其他value都与newValue使用mergeValue再合并为一个newValue。
                //最终同一个分区,每个key的多个value会合并为一个newValue。
                val partitionMergeRDD: RDD[(K, newV)] = rdd.mapPartitions(partIterator => {

                    //key和累加器的映射
                    val keyAndAccMap: mutable.Map[K, newV] = mutable.Map()

                    //遍历该分区的所有元素,每个元素都是k-v类型
                    partIterator.foreach(tuple => {
                        val key: K = tuple._1
                        val value: V = tuple._2

                        //如果是第一次碰到该key的数据,那么就使用value通过createCombiner创建一个新的newValue作为累加器初始值
                        if (!keyAndAccMap.contains(key)) {
                            val initValue: newV = createCombiner(value)
                            keyAndAccMap(key) = initValue
                        } else {
                            //旧累加器值
                            val oldAccValue: newV = keyAndAccMap(key)

                            //新累加器值=旧累加器值+当前k-v的value值
                            val newAccValue: newV = mergeValue(oldAccValue, value)
                            keyAndAccMap(key) = newAccValue
                        }
                    })

                    //此时当前分区内相同的key的所有value都最终合并为一个newValue
                    val iterator: Iterator[(K, newV)] = keyAndAccMap.iterator
                    iterator
                })


                //分区之间的数据,相同key的values使用mergeCombiners进行合并
                partitionMergeRDD.reduceByKey(mergeCombiners)
            }
        }

总结:reduceByKey底层就是用CombineByKey实现的。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值