欢迎关注我的新博客地址:http://cuipengfei.me/blog/2014/10/31/spark-fold-aggregate-why-not-foldleft/

大家都知道Scala标准库的List有一个用来做聚合操作的foldLeft方法。

比方我定义一个公司类:

1
case class Company(name:String, children:Seq[Company]=Nil)

它有名字和子公司。 然后定义几个公司:

1
val companies = List(Company("B"),Company("A"),Company("T"))

三家大公司,然后呢,我如果有一家超牛逼的公司把它们给合并了:

1
companies.foldLeft(Company("King"))((king,company)=>Company(name=king.name,king.children:+company))

这个运行的结果是这种:

1
2
scala> companies.foldLeft(Company("King"))((king,company)=>Company(name=king.name,king.children:+company))
res6: Company = Company(King,List(Company(B,List()), Company(A,List()), Company(T,List())))

可见foldLeft的结果是一家包括了BAT三大家得新公司。

由List[Company]聚合出一个新的Company,这样的属于foldLeft的同构聚合操作。

同一时候,foldLeft也能够做异构的聚合操作:

1
companies.foldLeft("")((acc,company)=>acc+company.name)

它的运行结果是这种:

1
2
scala> companies.foldLeft("")((acc,company)=>acc+company.name)
res7: String = BAT

由List[Company]聚合出一个String。

这种API感觉非常方便。仅仅要是聚合。不管同构异构。都能够用它来做。

近期接触了Spark,当中的RDD是做分布式计算时最经常使用的一个类。

RDD有一个叫做fold的API,它和foldLeft的签名非常像,唯一差别是它仅仅能做同构聚合操作。

也就是说假设你有一个RDD[X],通过fold,你仅仅能构造出一个X。

假设我想通过一个RDD[X]构造一个Y出来呢?

那就得用aggregate这个API了,aggregate的签名是这种:

1
aggregate[U](zeroValue: U)(seqOp: (U, T) ⇒ U, combOp: (U, U) ⇒ U)(implicit arg0: ClassTag[U]): U

它比fold和foldLeft多须要一个combOp做參数。

这让我非常不解,同构和异构的API干嘛非得拆成两个呢?怎么不能学Scala的标准库,把它做成类似foldLeft的样子呢?

后来想明确了,这是因为Spark须要分布运算造成的。

先想一下Scala List的foldLeft是怎么工作的?

1
companies.foldLeft(Company("King"))((king,company)=>Company(name=king.name,king.children:+company))
  1. 拿到初始值,即名字为king的公司,把它和list中的第一个公司合并,成为一个包括一家子公司的新公司
  2. 把上一步中的新公司拿来和list中的第二个公司合并,成为一个包括两家子公司的新公司
  3. 把上一步中的新公司拿来和list中的第三个公司合并,成为一个包括三家子公司的新公司

这是同构的过程。

1
companies.foldLeft("")((acc,company)=>acc+company.name)
  1. 拿到初始值,即空字符串。把它和list中的第一个公司的名字拼在一起,成为B
  2. 把上一步中的B第二个公司名字拼一起。成为BA
  3. 把上一步中的BA拿来和list中的第三个公司的名字拼一起,成为BAT

这是异构的过程。

像多米诺骨牌一样,从左到右依次把list中的元素吸收入结果中。

如今如果RDD[X]中有一个类似foldLeft的API,其签名和foldLeft一致,我如今调用foldLeft,给它一个f:(Y,X)=>Y,接下来该发生什么呢?

  1. 由于要分布计算,所以我先要把手里的非常多个X分成几份。分发到不同的节点上去
  2. 每一个节点把拿到的非常多个X计算出一个Y出来
  3. 把全部节点的结果拿来,这时我手里就有了非常多个Y
  4. 啊。。。我不知道怎么把非常多个Y变成一个Y啊。。。

因为Spark的RDD不像Scala的List一样仅仅须要推倒一副多米诺骨牌。而是要推倒非常多副。最后再对非常多副多米诺骨牌的结果做聚合。

这时假设是同构还好,我仅仅须要再用f:(X,X)=>X做一遍就ok了。

可是假设是异构的,那我就必须得再须要一个f:(Y,Y)=>Y了。

Spark RDD的fold和aggregate为什么是两个API?为什么不是一个foldLeft?的更多相关文章

  1. Apache Spark : RDD

    Resilient Distributed Datasets Resilient Distributed Datasets (RDD) is a fundamental data structure ...

  2. Spark RDD

    对RDD的学习进行一下整理 RDD:基于内存的集群计算容错抽象 分布式内存抽象的概念---弹性分布式数据集(RDD),它具备MapReduce等数据流模型的容错特性,并且允许开发人员在大型集群上执行基 ...

  3. Spark RDD概念学习系列之Spark的算子的分类(十一)

    Spark的算子的分类 从大方向来说,Spark 算子大致可以分为以下两类: 1)Transformation 变换/转换算子:这种变换并不触发提交作业,完成作业中间过程处理. Transformat ...

  4. spark RDD编程,scala版本

    1.RDD介绍:     RDD,弹性分布式数据集,即分布式的元素集合.在spark中,对所有数据的操作不外乎是创建RDD.转化已有的RDD以及调用RDD操作进行求值.在这一切的背后,Spark会自动 ...

  5. Spark RDD编程核心

    一句话说,在Spark中对数据的操作其实就是对RDD的操作,而对RDD的操作不外乎创建.转换.调用求值. 什么是RDD RDD(Resilient Distributed Dataset),弹性分布式 ...

  6. Spark RDD :Spark API--Spark RDD

    一.RDD的概述 1.1 什么是RDD? RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素 ...

  7. Spark Rdd coalesce()方法和repartition()方法

    在Spark的Rdd中,Rdd是分区的. 有时候需要重新设置Rdd的分区数量,比如Rdd的分区中,Rdd分区比较多,但是每个Rdd的数据量比较小,需要设置一个比较合理的分区.或者需要把Rdd的分区数量 ...

  8. Spark RDD aggregateByKey

    aggregateByKey 这个RDD有点繁琐,整理一下使用示例,供参考 直接上代码 import org.apache.spark.rdd.RDD import org.apache.spark. ...

  9. spark RDD transformation与action函数整理

    1.创建RDD val lines = sc.parallelize(List("pandas","i like pandas")) 2.加载本地文件到RDD ...

随机推荐

  1. 利用backtrace和ucontex定位segment错误【转】

    转自:https://blog.csdn.net/gqtcgq/article/details/53883546 C程序运行时,经常会碰到”segmentfault”错误.这是由于程序中非法访问内存导 ...

  2. start-stop-daemon 启动停止系统守护进程

    1.start-stop-daemon start-stop-daemon是一个Debian体系里的一个守护进程管理软件,可以用指定的用户启停软件.CentOS有自己的daemon()机制(在/etc ...

  3. idea如何编译maven项目

    这里我们介绍两种方式,如何调试出窗口 点击菜单栏View->Tool  Windows->Maven projects 点击菜单栏Help->Find Action(Ctrl+Shi ...

  4. MySQL安装与初步操作

    MySQL是一款出色的中小型关系数据库,做Java Web开发时,要做到数据持久化存储,选择一款数据库软件自然必不可少. 由于MySQL社区版开元免费,功能比较强大,在此以MySQL为例,演示MySQ ...

  5. 如何在Axure中使用FontAwesome字体图标

    Font Awesome为您提供可缩放的矢量图标,您可以使用CSS所提供的所有特性对它们进行更改,包括:大小.颜色.阴影或者其它任何支持的效果. FontAwesome应用在web网页开发中非常方便, ...

  6. MVC Autofac依赖注入

    通过Dll实现全部类的属性注入,该演示实例主要通过多层架构中单一的对象方式来演示,没有采取接口的方式, 新建AutoFacHelper类,如下代码: public class AutoFacHelpe ...

  7. wpf DataTemplate ColumnDefinition width equal

    <Grid.ColumnDefinitions> <ColumnDefinition SharedSizeGroup="col1" /> <Colum ...

  8. vue组件库(一):前期准备工作

    前言 将近期项目内自行开发一个vue组件,做个总结,记录下自己的思维过程~~~ 正文 接到这个任务后,还是要做些准备工作的. 主要内容如下: 1.优化下所在团队前端开发流程 服务器搭建gitlab,采 ...

  9. SQL Server 2

    一.创建数据表 1.连接服务器: 2.右击“表”节点,选择“新建表”,即: 3.在弹出的“表设计器”中,输入表的列名.选择的数据类型及是否允许为空,即: 二.导入数据表 1.右击表名,弹出菜单,选择“ ...

  10. 为什么因式分解n=pq分别得到pq是求解密钥中d的关键

    从d的来源来说,它是这样来的: "找到一个数d,使得ed-1能够被z整除.即给定e,选择数d,使得ed被z除的余数为1",即  ed=1 (mod z) 上面这句话中,为了求d,我 ...