简单介绍

combineByKey()是最通用的对key-value型rdd进行聚集操作的聚集函数(aggregation function)。类似于aggregate(),combineByKey()允许用户返回值的类型与输入不一致。

其定义如下,我们可以根据这个形式来分别定义createCombiner、mergeValue和mergeCombiners三个函数:

def combineByKey[C](
  createCombiner: V => C, ##A
  mergeValue: (C, V) => C, ##B
  mergeCombiners: (C, C) => C,##C 
  partitioner: Partitioner,   
  mapSideCombine: Boolean = true,
  serializer: Serializer = null

)

自定义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合并到之前的元素C(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])

案例:

如图,有两个分区,key-value(类别-数量)形式也清楚,我们想知道coffee的平均数量和panda的平均数量。以scala形式写法如下:

val init_data = Array(("coffee", 1), ("coffee", 2), ("panda", 3), ("coffee", 9))
val data = sc.parallelize(init_data) # 两个分区
type MVType = (Int, Int) //定义一个元组类型
data.combineByKey(
   score => (1, score), # createCombiner函数
   (c: MVType, newScore) => (c._1 + 1, c._2 + newScore), # mergeValue函数
   (c1: MVType, c2: MVType) => (c1._1 + c2._1, c1._2 + c2._2) # mergeCombiners函数
).map { case (key, value) => (key, value._2/ value._1) }.map(println(_))

分析:

Partition 1 trace:
(coffee, 1) => new key
accumulators[coffee] = createCombiner(1)
得到:(coffee, (1, 1))
(coffee, 2) => existing key
accumulators[coffee] = mergeValue(accumulators[coffee], 2)
得到:(coffee, (2, 3))
显然(panda, 3) => new key,调用createCombiner方法。
得到:(panda, (1, 3))

Partition 2 trace:
(coffee, 9) => new key
accumulators[coffee] = createCombiner(9)
得到:(coffee, (1, 9))

接下来,mergeCombiners来合并分区:

Merge Partitions
mergeCombiners(partition1.accumulators[coffee], partition2.accumulators[coffee])
得到:(coffee, (3,12))

---------------------------------------------细心看 反复看 不然是假懂--------------------------------

讲明白combineByKey()算子,不是谈源码的更多相关文章

  1. sobel算子原理及opencv源码实现

    sobel算子原理及opencv源码实现 简要描述 sobel算子主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测. 原理 算子使用两个33的矩阵(图1)算子使用两个33的矩阵(图1)去 ...

  2. 手把手教你使用LabVIEW人工智能视觉工具包快速实现传统Opencv算子的调用(含源码)

    前言 今天我们一起来使用LabVIEW AI视觉工具包快速实现图像的滤波与增强:图像灰度处理:阈值处理与设定:二值化处理:边缘提取与特征提取等基本操作.工具包的安装与下载方法可见之前的博客. 一.图像 ...

  3. 阿里P7终于讲完了JDK+Spring+mybatis+Dubbo+SpringMvc+Netty源码

    前言 这里普及一下,每个公司都有职别定级系统,阿里也是,技术岗以 P 定级,一般校招 P5, 社招 P6 起.其实阅读源码也是有很多诀窍的,这里分享几点心得: 首先要会用.你要知道这个库是干什么的,掌 ...

  4. cache2go源码最后一讲 - examples

    先看一下我们讲到哪里了: cache2go的源码前面我们已经讲完了cacheitem和cachetable的实现,今天cahce和examples会一起讲完~ 1.cache.go源码 ​      ...

  5. LinqToDB 源码分析——DataContext类

    LinqToDB框架是一个轻量级的ORM框架.当然,功能上来讲一定比不上Entity Framework的强大.但是在使用上总让笔者感觉有一点Entity Framework的影子.笔者想过可能的原因 ...

  6. 详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]

    目录 前言 现象 源码分析 HandlerMethodArgumentResolver与HandlerMethodReturnValueHandler接口介绍 HandlerMethodArgumen ...

  7. HashMap 源码详细分析(JDK1.8)

    一.概述 本篇文章我们来聊聊大家日常开发中常用的一个集合类 - HashMap.HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现.HashMap 允许 null 键和 null 值, ...

  8. 深入出不来nodejs源码-流程总览

    花了差不多两周时间过了下primer C++5th,完成了<C++从入门到精通>.(手动滑稽) 这两天看了下node源码的一些入口方法,其实还是比较懵逼的,语法倒不是难点,主要是大量的宏造 ...

  9. 【MVC - 参数原理】详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]

    前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/spring ...

随机推荐

  1. java中interface 的特性

    有时必须从几个类中派生出一个子类,继承它们所有的属性和方法.但是,Java不支持多重继承.有了接口,就可以得到多重继承的效果. 接口(interface)是抽象方法和常量值的定义的集合.从本质上讲,接 ...

  2. jdk、tomcat如何配置环境变量

    一.安装JDK和Tomcat 1,安装JDK:直接运行jdk-7-windows-i586.exe可执行程序,默认安装即可. 备注:路径可以其他盘符,不建议路径包含中文名及特殊符号. 2.安装Tomc ...

  3. 重学JAVA基础(五):面向对象

    1.封装 import java.util.Date; public class Human { protected String name; protected BirthDay birthDay; ...

  4. C#编译问题'System.Collections.Generic.IEnumerable' does not contain a definition for 'Where' and no extension method 'Where' accepting a first argument

    &apos;System.Collections.Generic.IEnumerable<string>&apos; does not contain a definiti ...

  5. No overload for 'OnStartup' matches delegate 'System.Windows.StartupEventHandler'

    No overload for &apos;OnStartup&apos; matches delegate &apos;System.Windows.StartupEvent ...

  6. 实训随笔2:Git Gui——拯救菜鸟的工具

    熟练使用git进行多人协作开发,是程序猿必备的专业技能之一,可惜我等实在太菜搞不来复杂的命令行. 幸好除了Git Bash还有一个Git gui存在——专门为了拯救我们这些菜鸡程序猿而存在的工具. 下 ...

  7. 存储过程为参数NULL时的处理方法

    准备一些数据: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Goods]( ) NULL, ) NULL, ...

  8. Netdata 是一款 Linux 性能实时监测工具

    具体的netdata介绍请参照GIT:https://github.com/firehol/netdata/wiki 以下只介绍centos下的netdata的安装与使用: 1.安装Netdata需要 ...

  9. org.apache.commons.httpclient和org.apache.http.client区别(转)

    官网说明: http://hc.apache.org/httpclient-3.x/ Commons HttpClient项目现已结束,不再开发.它已被其HttpClient和HttpCore模块中的 ...

  10. C#中的结构体要使用new来实例化吗?

    声明结构的默认(无参数)构造函数是错误的.总是提供默认构造函数以将结构成员初始化为它们的默认值.在结构中初始化实例字段也是错误的. 如果使用 new 运算符创建结构对象,则会创建该结构对象,并调用适当 ...