https://blog.csdn.net/u013514928/article/details/56680825

1. aggregate函数

将每个分区里面的元素进行聚合,然后用combine函数将每个分区的结果和初始值(zeroValue)进行combine操作。这个函数最终返回的类型不需要和RDD中元素类型一致。

seqOp操作会聚合各分区中的元素,然后combOp操作把所有分区的聚合结果再次聚合,两个操作的初始值都是zeroValue.   seqOp的操作是遍历分区中的所有元素(T),第一个T跟zeroValue做操作,结果再作为与第二个T做操作的zeroValue,直到遍历完整个分区。combOp操作是把各分区聚合的结果,再聚合。aggregate函数返回一个跟RDD不同类型的值。因此,需要一个操作seqOp来把分区中的元素T合并成一个U,另外一个操作combOp把所有U聚合。

例子程序:

  1. scala> val rdd = List(1,2,3,4,5,6,7,8,9)
  2. rdd: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
  1. <span style="color:#330000;">
  2. scala> rdd.par.aggregate((0,0))(
  3. (acc,number) => (acc._1 + number, acc._2 + 1),
  4. (par1,par2) => (par1._1 + par2._1, par1._2 + par2._2)
  5. )
  6. res0: (Int, Int) = (45,9)
  7. scala> res0._1 / res0._2
  8. res1: Int = 5
  9. 过程大概这样:
  10. 首先,初始值是(0,0),这个值在后面2步会用到。
  11. 然后,(acc,number) => (acc._1 + number, acc._2 + 1),number即是函数定义中的T,这里即是List中的元素。所以acc._1 + number,acc._2 + 1的过程如下。
  12. 1.  0+1,  0+1
  13. 2.  1+2,  1+1
  14. 3.  3+3,  2+1
  15. 4.  6+4,  3+1
  16. 5.  10+5,  4+1
  17. 6.  15+6,  5+1
  18. 7.  21+7,  6+1
  19. 8.  28+8,  7+1
  20. 9.  36+9,  8+1
  21. </span><strong><span style="color:#ff0000;">结果即是(45,9)</span></strong><span style="color:#330000;">。这里演示的是单线程计算过程,实际Spark执行中是分布式计算,可能会把List分成多个分区,假如3个,p1(1,2,3,4),p2(5,6,7,8),p3(9),经过计算各分区的的结果(10,4),(26,4),(9,1),这样,执行(par1,par2) =>(par1._1 + par2._1, par1._2 + par2._2)就是(10+26+9,4+4+1)即(45,9),再求平均值就简单了。</span>

2. aggregateByKey函数:

对PairRDD中相同的Key值进行聚合操作,在聚合过程中同样使用了一个中立的初始值。和aggregate函数类似,aggregateByKey返回值的类型不需要和RDD中value的类型一致。因为aggregateByKey是对相同Key中的值进行聚合操作,所以aggregateByKey'函数最终返回的类型还是PairRDD,对应的结果是Key和聚合后的值,而aggregate函数直接返回的是非RDD的结果。

例子程序:

  1. <span style="font-family:'Times New Roman';font-size:18px;">import org.apache.spark.SparkConf
  2. import org.apache.spark.SparkContext
  3. object AggregateByKeyOp {
  4. def main(args:Array[String]){
  5. val sparkConf: SparkConf = new SparkConf().setAppName("AggregateByKey").setMaster("local")
  6. val sc: SparkContext = new SparkContext(sparkConf)
  7. val data=List((1,3),(1,2),(1,4),(2,3))
  8. val rdd=sc.parallelize(data, 2)
  9. //合并不同partition中的值,a,b得数据类型为zeroValue的数据类型
  10. def combOp(a:String,b:String):String={
  11. println("combOp: "+a+"\t"+b)
  12. a+b
  13. }
  14. //合并在同一个partition中的值,a的数据类型为zeroValue的数据类型,b的数据类型为原value的数据类型
  15. def seqOp(a:String,b:Int):String={
  16. println("SeqOp:"+a+"\t"+b)
  17. a+b
  18. }
  19. rdd.foreach(println)
  20. //zeroValue:中立值,定义返回value的类型,并参与运算
  21. //seqOp:用来在同一个partition中合并值
  22. //combOp:用来在不同partiton中合并值
  23. val aggregateByKeyRDD=rdd.aggregateByKey("100")(seqOp, combOp)
  24. sc.stop()
  25. }
  26. }</span>

运行结果:

将数据拆分成两个分区

//分区一数据
(1,3)
(1,2)
//分区二数据
(1,4)
(2,3) //分区一相同key的数据进行合并
seq: 100 3 //(1,3)开始和中立值进行合并 合并结果为 1003
seq: 1003 2 //(1,2)再次合并 结果为 10032 //分区二相同key的数据进行合并
seq: 100 4 //(1,4) 开始和中立值进行合并 1004
seq: 100 3 //(2,3) 开始和中立值进行合并 1003 将两个分区的结果进行合并
//key为2的,只在一个分区存在,不需要合并 (2,1003)
(2,1003) //key为1的, 在两个分区存在,并且数据类型一致,合并
comb: 10032 1004
(1,100321004)

Spark操作—aggregate、aggregateByKey详解的更多相关文章

  1. Spark算子篇 --Spark算子之aggregateByKey详解

    一.基本介绍 rdd.aggregateByKey(3, seqFunc, combFunc) 其中第一个函数是初始值 3代表每次分完组之后的每个组的初始值. seqFunc代表combine的聚合逻 ...

  2. Spark算子之aggregateByKey详解

    一.基本介绍 rdd.aggregateByKey(3, seqFunc, combFunc) 其中第一个函数是初始值 3代表每次分完组之后的每个组的初始值. seqFunc代表combine的聚合逻 ...

  3. Spark log4j日志配置详解(转载)

    一.spark job日志介绍    spark中提供了log4j的方式记录日志.可以在$SPARK_HOME/conf/下,将 log4j.properties.template 文件copy为 l ...

  4. IOS数据库操作SQLite3使用详解(转)

    iPhone中支持通过sqlite3来访问iPhone本地的数据库.具体使用方法如下1:添加开发包libsqlite3.0.dylib首先是设置项目文件,在项目中添加iPhone版的sqlite3的数 ...

  5. [Spark内核] 第36课:TaskScheduler内幕天机解密:Spark shell案例运行日志详解、TaskScheduler和SchedulerBackend、FIFO与FAIR、Task运行时本地性算法详解等

    本課主題 通过 Spark-shell 窥探程序运行时的状况 TaskScheduler 与 SchedulerBackend 之间的关系 FIFO 与 FAIR 两种调度模式彻底解密 Task 数据 ...

  6. [转]使用python来操作redis用法详解

    转自:使用python来操作redis用法详解 class CommRedisBase(): def __init__(self): REDIS_CONF = {} connection_pool = ...

  7. C语言对文件的操作函数用法详解2

    fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const  ...

  8. C语言对文件的操作函数用法详解1

    在ANSIC中,对文件的操作分为两种方式,即: 流式文件操作 I/O文件操作 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下: typedef str ...

  9. python操作redis用法详解

    python操作redis用法详解 转载地址 1.redis连接 redis提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用 ...

  10. iBatis——自动生成DAO层接口提供操作函数(详解)

    iBatis——自动生成DAO层接口提供操作函数(详解) 在使用iBatis进行持久层管理时,发现在使用DAO层的updateByPrimaryKey.updateByPrimaryKeySelect ...

随机推荐

  1. Lambda中的常用sql方法

    1.Groupby 对集合进行分组,如: var dllList = _menuMan.Load(c => c.TXT_ASSEMBLYNAME != null).GroupBy(c=>c ...

  2. ubuntu 16.04更新软件源

    1.打开 system settings 2.打开 system栏目里的 software and updates 3.打开 ubuntu software 栏目里的 download from 4. ...

  3. maven项目引入外部jar包的三种方式

    方式1:dependency 本地jar包 <dependency> <groupId>com.hope.cloud</groupId> <!--自定义--& ...

  4. c++builder 编译独立运行

    cb6 XE7 Project>Options> Packages>Runtime Packages>Link with runtime packags勾去掉.c++ Link ...

  5. ubuntu12 安装redis和phpRedisAdmin详细流程

    一.Ubuntu安装redis(redis默认端口6379) 方式一.直接下载源码,编译(redis可以编译源码之后直接运行,不需要安装) 1.1执行命令,从官网下载源码编译: $ wget http ...

  6. webpack4+vue2+axios+vue-router的多页+单页混合应用框架

    VUE2的单页应用框架有人分享了,多页应用框架也有人分享了,这里就分享一个单页和多页的混合应用框架吧,初现雏形,还有很多需要优化和改善的地方... 结尾有github地址. 项目结构 │ ├─buil ...

  7. 并发之AtomicIntegerArray

    5 并发之AtomicIntegerArray     该类是Java对Integer数组支持的原子性操作:在认识这个类之前我们先来看一个方法,这个方法是Integer类中的:  public sta ...

  8. 开坑数位dp

    [背景] 在10月3日的dp专练中,压轴的第6题是一道数位dp,于是各种懵逼. 为了填上这个留存已久的坑,蒟蒻chty只能开坑数位dp了. [例题一][HDU2089]不要62 题目大意:给你一个区间 ...

  9. Android selector中的item的顺序

    在selector中,要将默认状态的item放在最后面,因为一旦前面的item满足匹配条件,后面的item就不会去匹配.因此,把默认状态的item放在前面的话,后面的item没有执行的机会

  10. Windows下Memcached的安装配置方法

    1.将第一个包解压放某个盘下面,比如在c:\memcached. 2.在终端(也即cmd命令界面)下输入 'c:\memcached\memcached.exe -d install' 安装. 3.再 ...