1:groupByKey

def groupByKey(): RDD[(K, Iterable[V])]

根据key进行聚集,value组成一个列表,没有进行聚集,所以在有shuffle操作时候避免使用概算子,会增大通信数据量。需要考虑进行一个本地的Combiner,所以可以直接使用reduceByKey

cala> p.collect
res15: Array[(Int, Int)] = Array((1,1), (2,1), (1,1), (2,1), (1,1), (2,1), (3,1), (4,1), (5,1)) scala> p.groupByKey.collect
res16: Array[(Int, Iterable[Int])] = Array((4,CompactBuffer(1)), (2,CompactBuffer(1, 1, 1)), (1,CompactBuffer(1, 1, 1)), (3,CompactBuffer(1)), (5,CompactBuffer(1)))

2:cogroup

def cogroup[W](other: RDD[(K, W)], partitioner: Partitioner): RDD[(K, (Iterable[V], Iterable[W]))]

对每一个rdd先进行groupByKey,然后在对相同key的value在进行一个groupByKey,例如

scala> p.collect
res18: Array[(Int, Int)] = Array((1,1), (2,1), (1,1), (2,1), (1,1), (2,1), (3,1), (4,1), (5,1)) scala> p.cogroup(p).collect
res19: Array[(Int, (Iterable[Int], Iterable[Int]))] = Array((4,(CompactBuffer(1),CompactBuffer(1))), (2,(CompactBuffer(1, 1, 1),CompactBuffer(1, 1, 1))), (1,(CompactBuffer(1, 1, 1),CompactBuffer(1, 1, 1))), (3,(CompactBuffer(1),CompactBuffer(1))), (5,(CompactBuffer(1),CompactBuffer(1))))

例如:(1,1)在pair中出现三次,所以cogroup之后(1,1)的结果是:

(1,(CompactBuffer(1, 1, 1),CompactBuffer(1, 1, 1)))

3:aggregateByKey

def aggregateByKey[U](zeroValue: U)(seqOp: (U, V) ⇒ U, combOp: (U, U) ⇒ U)(implicit arg0: ClassTag[U]): RDD[(K, U)]

说明:这个函数相对有点难懂,其他重载版本与此类似。该函数接受三个参数,一个初始值,两个函数:seqOp和comOp:

seqOp是对分区进行具体的函数,zeroValue值只有在seqOp中有使用,在第二个函数comOp中就不在使用了。

comOp是分区之间的combine函数(combine函数有点类似combiner的作用,进行聚集的函数)。

例如:

    val data = sc.parallelize(List((1, 3), (1, 2), (1, 4), (2, 3), (2, 5)))
def seq(a: Int, b: Int): Int = {
println("seq: " + a + "\t " + b)
math.max(a, b)
}
def comb(a: Int, b: Int): Int = {
println("comb: " + a + "\t " + b)
a + b
}

执行过程输出:

seq: 1     3
seq: 1 2
seq: 1 4
seq: 1 3
seq: 1 5
comb: 3 2
comb: 5 4
comb: 3 5

说明:在调用seqOp函数时候,每一次都向(key,value)中的value和zeroValue进行求最大值,将该最大值作为key的value。执行完毕seqOp函数的状态为:

((1,(3,2,4)),(2(3,5)))

然后调用comOp函数将每一个key的value进行累加,得到最后输出。

输出:

scala> data.aggregateByKey(1)(seq, comb).collect.toBuffer
res36: scala.collection.mutable.Buffer[(Int, Int)] = ArrayBuffer((2,5), (1,7))

4:combineByKey

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

参数说明:

  • createCombiner, which turns a V into a C (e.g., creates a one-element list)
  • mergeValue, to merge a V into a C (e.g., adds it to the end of a list)
  • mergeCombiners, to combine two C's into a single one.

例如:

val data1 = sc.parallelize(List("a", "b", "c", "c", "b", "a", "b", "a"))
val data2 = sc.parallelize(List(1, 2, 3, 3, 2, 1, 2, 1))
val zip = data2.zip(data1)
val combineByKey = zip.combineByKey(List(_), (x: List[String], y: String) => y :: x, (x: List[String], y: List[String]) => x ::: y)
println(combineByKey.collect().toBuffer)

输出:

ArrayBuffer((1,List(a, a, a)), (2,List(b, b, b)), (3,List(c, c)))

5:flatMapValues

def flatMapValues[U](f: (V) ⇒ TraversableOnce[U]): RDD[(K, U)]

传入一个键值对的值给 (V) ⇒ TraversableOnce[U]函数,返回的是一个集合的函数。将当前的key和当前集合中每一个元素组成元组返回

val a = sc.parallelize(List((1,2),(3,4),(5,6)))
val b = a.flatMapValues(x=>1 to x)
b.collect.foreach(println(_))

输出:

(1,1)
(1,2)
(3,1)
(3,2)
(3,3)
(3,4)
(5,1)
(5,2)
(5,3)
(5,4)
(5,5)
(5,6)

分析:当传入是2的时候,生成一个1 to 2 的序列,然后当前key=1,所以生成(1,1),(1,2)两个元组、

 6:foldByKey

def foldByKey(zeroValue: V)(func: (V, V) ⇒ V): RDD[(K, V)]

fold:折叠的意思,根据key进行折叠,例如:

scala> rdd.collect
res2: Array[String] = Array(hello, world, xiaomi, meizu, meizu) scala> rdd.map((_,1)).foldByKey(1)(_+_).collect
res3: Array[(String, Int)] = Array((meizu,3), (hello,2), (world,2), (xiaomi,2))

此处zeroValue为1,由于meizu这个字符出现两次并加上zeroValue的话恰好是3。hello world xiaomi这些单词都是一次,并加上zeroValue恰好是2。

当zeroValue值为0的时候,我们可以实现一个wordcount。

7:mapValues

def mapValues[U](f: (V) ⇒ U): RDD[(K, U)]

对键值对的每一个value进行处理,key保持不变。例如:我对现有的键值对的值进行乘以10的操作

scala> rdd.map((_,1)).collect
res14: Array[(String, Int)] = Array((hello,1), (world,1), (xiaomi,1), (meizu,1), (meizu,1)) scala> rdd.map((_,1)).mapValues(x=>x*10).collect
res15: Array[(String, Int)] = Array((hello,10), (world,10), (xiaomi,10), (meizu,10), (meizu,10))

8:rightOuterJoin

def rightOuterJoin[W](other: RDD[(K, W)], numPartitions: Int): RDD[(K, (Option[V], W))]

右外连接,other中的所有key都会出现在结果中,关联到的是一个Some值,关联不到的是一个None。例如:

scala> rdd1.collect
res26: Array[(Int, Int)] = Array((1,1), (2,1), (3,1), (4,1), (5,1)) scala> rdd2.collect
res27: Array[(Int, Int)] = Array((3,2), (4,2), (5,2), (6,2), (7,2), (8,2)) scala> rdd1.rightOuterJoin(rdd2).collect
res28: Array[(Int, (Option[Int], Int))] = Array((4,(Some(1),2)), (6,(None,2)), (8,(None,2)), (3,(Some(1),2)), (7,(None,2)), (5,(Some(1),2)))

9:leftOuterJoin

def leftOuterJoin[W](other: RDD[(K, W)]): RDD[(K, (V, Option[W]))]

同上面右外连接。示例:

scala> rdd1.collect
res31: Array[(Int, Int)] = Array((1,1), (2,1), (3,1), (4,1), (5,1)) scala> rdd2.collect
res32: Array[(Int, Int)] = Array((3,2), (4,2), (5,2), (6,2), (7,2), (8,2)) scala> rdd1.leftOuterJoin(rdd2).collect
res33: Array[(Int, (Int, Option[Int]))] = Array((4,(1,Some(2))), (2,(1,None)), (1,(1,None)), (3,(1,Some(2))), (5,(1,Some(2))))

rdd中的所有的key都会出现,关联的不到的为None,此时关联的值在value的第二个位置。我们可以通过交换右外连接的两个rdd的位置,实现左外连接,但是区别在于value中元素的位置是逆序的:

scala> rdd2.rightOuterJoin(rdd1).collect //通过右外连接实现左外连接
res34: Array[(Int, (Option[Int], Int))] = Array((4,(Some(2),1)), (2,(None,1)), (1,(None,1)), (3,(Some(2),1)), (5,(Some(2),1)))

键值对的算子讲解 PairRDDFunctions的更多相关文章

  1. 【Spark】RDD操作具体解释3——键值型Transformation算子

    Transformation处理的数据为Key-Value形式的算子大致能够分为:输入分区与输出分区一对一.聚集.连接操作. 输入分区与输出分区一对一 mapValues mapValues:针对(K ...

  2. Spark常用函数讲解之键值RDD转换

    摘要: RDD:弹性分布式数据集,是一种特殊集合 ‚ 支持多种来源 ‚ 有容错机制 ‚ 可以被缓存 ‚ 支持并行操作,一个RDD代表一个分区里的数据集RDD有两种操作算子:         Trans ...

  3. OC键值观察KVO

    什么是KVO? 什么是KVO?KVO是Key-Value Observing的简称,翻译成中文就是键值观察.这是iOS支持的一种机制,用来做什么呢?我们在开发应用时经常需要进行通信,比如一个model ...

  4. Spark 键值对RDD操作

    键值对的RDD操作与基本RDD操作一样,只是操作的元素由基本类型改为二元组. 概述 键值对RDD是Spark操作中最常用的RDD,它是很多程序的构成要素,因为他们提供了并行操作各个键或跨界点重新进行数 ...

  5. 分布式键值存储系统ETCD调研

    分布式键值存储系统ETCD调研 简介 etcd是一个开源的分布式键值存储工具--为CoreOS集群提供配置服务.发现服务和协同调度.Etcd运行在集群的每个coreos节点上,可以保证coreos集群 ...

  6. Spark学习之键值对操作总结

    键值对 RDD 是 Spark 中许多操作所需要的常见数据类型.键值对 RDD 通常用来进行聚合计算.我们一般要先通过一些初始 ETL(抽取.转化.装载)操作来将数据转化为键值对形式.键值对 RDD ...

  7. XamarinEssentials教程移除键值首选项的键值

    XamarinEssentials教程移除键值首选项的键值 如果开发者不再使用首选项中的某一项时,可以将该项移除掉.此时可以使用Preferences类的Remove()方法,该方法可以将存在于首选项 ...

  8. 各种Map的区别,想在Map放入自定义顺序的键值对

    今天做统计时需要对X轴的地区按照地区代码(areaCode)进行排序,由于在构建XMLData使用的map来进行数据统计的,所以在统计过程中就需要对map进行排序. 一.简单介绍Map 在讲解Map排 ...

  9. ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml) 用javascript在客户端删除某一个cookie键值对 input点击链接另一个页面,各种操作。 C# 往线程里传参数的方法总结 TCP/IP 协议 用C#+Selenium+ChromeDriver 生成我的咕咚跑步路线地图 (转)值得学习百度开源70+项目

    ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml)   我们都知道在使用WebApi的时候Controller会自动将Action的返回值自动进行各种序列化处理(序列化为 ...

随机推荐

  1. scikit-learn入门导航

    scikit-learn是一个非常强大的机器学习库, 提供了很多常见机器学习算法的实现. scikit-learn可以通过pip进行安装: pip install -U scikit-learn 不过 ...

  2. [JLOI 2016]成绩比较

    Description 题库链接( \(\text{bzoj}\) 不知道为什么过不了啊... \(\text{luogu loj}\) 都能过...就给 \(\text{luogu}\) 的链接了. ...

  3. Nginx反代Mogilefs分布式储存示例

    一.分布式存储系统简介 随着信息技术不断的发展,给我们带来便利的同时,不断增加的数据量级.信息之间的连接关联越来越复杂.数据访问的并发量日益增加对I/O的要求越来越高.数据类型越来越复杂等难题也成为信 ...

  4. Linux中ansible批量管理软件部署及剧本编写

    服务器版本信息: Centos6.9 [root@db02 ~]# uname -a Linux db02 2.6.32-696.el6.x86_64 #1 SMP Tue Mar 21 19:29: ...

  5. cannot import name 'Flask' from 'flask'

    今天发现了智障的真我. 刚入门flask,建了一个文件命名叫flask.py 在virtualenv的容器里运行该py文件,报错cannot import name 'Flask' from 'fla ...

  6. C#基础 数据类型 类型转换

    本节主要讲解数据类型和各类型之间的转换,两点都是重点,难点在于各种转换的活学活用. 一   数据类型 (一)基本数据类型 1  值类型 (1)整形         int                ...

  7. Asp.Net MVC3 简单入门详解过滤器Filter(转载)

    前言 在开发大项目的时候总会有相关的AOP面向切面编程的组件,而MVC(特指:Asp.Net MVC,以下皆同)项目中不想让MVC开发人员去关心和写类似身份验证,日志,异常,行为截取等这部分重复的代码 ...

  8. Strange Way to Express Integers(中国剩余定理+不互质)

    Strange Way to Express Integers Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%I64d & ...

  9. JS调用模式

    在js中,一共4中调用方式.需要注意的是,调用方式中,this的指向问题. 函数调用模式 this丢失,debug会提示未定义相应属性.按照规范,需要将this赋值给that let myObj = ...

  10. css文本溢出隐藏显示省略号(单行+多行)

    文本超出若干行就换行,这个功能几乎每个文本浏览网站都会用到,实现它的办法也有很多,今天简单的介绍一下实现它的方法.  一. 单行文本不换行,并将超出文本隐藏 .box-content{     ove ...