04、常用RDD操作整理
常用Transformation
注:某些函数只有PairRDD只有,而普通的RDD则没有,比如gropuByKey、reduceByKey、sortByKey、join、cogroup等函数要根据Key进行分组或直接操作
RDD基本转换: |
|||
RDD[U] T:原RDD中元素类型 U:新RDD中元素类型 |
函数将T元素转换为新的U元素 |
rdd.map(x |
{1, 2, 3, 3} =>{2, |
RDD[U] TraversableOnce:集合与迭代器的父类 |
函数将T元素转换为含有新类型U元素的集合,并将这些集合展平(两层转换成一层)后的元素形成新的RDD |
rdd.flatMap(x |
{1, 2, 3, 3} =>{1, |
RDD[T] |
函数对每个元素进行过滤,通过的元素形成新的RDD |
rdd.filter(x |
{1, 2, 3, 3} =>{2, |
RDD[T] |
去重 |
rdd.distinct() |
{1, 2, 3, 3} =>{1, |
RDD[U] |
与map一样,只是转换时是以分区为单位,将一个分区所有元素包装成Iterator一次性传入函数进行处理,而不像map函数那样每个元素都会调用一个函数,即这里有几个分区则才调用几次函数 假设有N个元素,有M个分区,那么map的函数的将被调用N次,而mapPartitions被调用M次 |
val arr = Array(1, 2, 3, 4, 5) val rdd = sc.parallelize(arr, 2) rdd.mapPartitions((it: |
=>{2, 4, 6, 8, 10} |
RDD[U] |
与mapPartitions类似,不同的时函数多了个分区索引的参数 |
||
RDD[T] |
两个RDD 并集,包括重复的元素 |
rdd.union(otherRdd) |
{ 1, 2, 2, 3, 3} { 3, 4, 5} =>{1, |
RDD[T] |
两个RDD 交集 |
rdd.intersection(otherRdd) |
{ 1, 2, 2, 3, 3} { 3, 4, 5} =>{3} |
RDD[T] |
两个RDD相减 |
rdd.subtract(otherRdd) |
{ 1, 2, 2, 3, 3} { 3, 4, 5} =>{1, |
RDD[(T, |
两个RDD相减笛卡儿积 |
rdd.cartesian(otherRdd) |
{ 1, 2 } { 3, 4} =>{(1,3),(1,4),(2,3),(2,4)} |
RDD[T] |
根据转换后的值进行排序,传入的是一个(T) => K 转换函数 |
rdd.sortBy(_._2, 这里根据value进行降序排序 |
{("leo", 65), ("tom", 50), ("marry", 100), =>{("marry", |
RDD[Array[T]] |
将RDD的每个分区中的类型为T的元素转换换数组Array[T] |
val arr = Array(1, 2, 3, 4, 5) val rdd = sc.parallelize(arr, 2) val arrRDD = rdd.glom()arrRDD.foreach { =>[ 1 2 ], [ 3 4 5 ] |
|
键-值RDD转换: |
|||
RDD[(K, K:key类型 V:value类型 |
将value转换为新的U元素,Key不变 |
rdd.mapValues(_ |
{"class1", 80), ("class2", 70)} =>{"class1", |
RDD[(K, |
对[K,V]型数据中的V值flatmap操作 |
rdd.flatMapValues(_.toCharArray()) |
{ (1, "ab"), (2, "bc")} =>{(1, |
RDD[(K, |
根据key进行分组,同一组的元素组成Iterable<V>,并以(key, Iterable<V>)元组类型为元素作为新的RDD返回 |
rdd.groupByKey() |
{("class1", 80), ("class2", 75), =>{("class1",[80,90]),("class2",[75,60])} |
RDD[(K, T:原RDD元素类型 K:新RDD中元素Key的类型 |
根据函数将元素T映射成相应K后,以此K进行分组 |
rdd.groupBy({ |
{ 1, 2, "二" =>{(1,[1]),(2,[2, |
RDD[(K, |
先根据key进行分组,再对同一组中的的value进行reduce操作:第一次调用函数时传入的是两个Key所对应的value,从第二次往后,传入的两个参数中的第一个为上次函数计算的结果,第二个参数为其它Key的value |
rdd. |
{("class1", 80), ("class2", 75), =>{("class1", |
RDD[(K, |
根据key的大小进行排序(注:并不是先以Key进行分组,再对组类进行排序,而是直接根据Key的值进行排序) |
rdd.sortByKey(false) |
{(65, "leo"), (50, "tom"),(100, =>{(100, |
|
|||
RDD[(K, zeroValue:每个分区相同Key累计时的初始值,以及不同分区相同Key合并时的初始值 e.g., Nil for list concatenation, 0 |
对每个value先进行func操作,且funcfoldByKey函数是通过调用comineByKey函数实现的。 zeroVale:对V进行初始化,实际上是通过CombineByKey的createCombiner实现的 V => func: Value将通过func函数按Key值进行合并(实际上是通过CombineByKey的mergeValue,mergeCombiners函数实现的,只不过在这里,这两个函数是相同的) |
val people = List(("Mobin", 1), ("Lucy", 2), ("Amy", 3), ("Amy", 4), ("Lucy", 5)) val rdd = sc.parallelize(people,2) val foldByKeyRDD = rdd.foldByKey(10)((v1, v2) foldByKeyRDD.foreach(println) |
//处理第一个分区数据 10 + 1 = 11 // ("Mobin", 10 + 2 = 12 // ("Lucy", ===================== //处理第二个分区数据 10 + 3 = 13 // ("Amy", 3) 13 + 4 10 + 5 = 15 // ("Lucy", ===================== //将不同分区相同Key的Value合并起来 12 + (Amy,17) (Mobin,11) (Lucy,27) |
RDD[(K, |
左外连接,包含左RDD的所有数据,如果右边没有与之匹配的用None表示 |
val arr = List(("A", 1), ("A", 2), ("B", 1)) val arr1 = List(("A", "A1"), ("A", "A2")) val rdd = sc.parallelize(arr, 2) val rdd1=sc.parallelize(arr1, 2) val leftOutJoinRDD = rdd.leftOuterJoin(rdd1) leftOutJoinRDD.foreach(println) |
=> (B,(1,None)) (A,(1,Some(A1))) (A,(1,Some(A2))) (A,(2,Some(A1))) (A,(2,Some(A2))) |
RDD[(K, |
右外连接,包含右RDD的所有数据,如果左边没有与之匹配的用None表示 |
val arr = List(("A", 1), ("A", 2)) val arr1 = List(("A", "A1"), ("A", "A2"), ("B", 1)) val rdd = sc.parallelize(arr, 2) val rdd1 = sc.parallelize(arr1, 2) val leftOutJoinRDD = rdd.rightOuterJoin(rdd1) leftOutJoinRDD.foreach(println) |
(B,(None,1)) (A,(Some(1),A1)) (A,(Some(1),A2)) (A,(Some(2),A1)) (A,(Some(2),A2)) |
RDD[(K, W:另一RDD元素的value的类型 |
对两个包含<key,value>对的RDD根据key进行join操作,返回类型<key,Tuple2(key,value)> |
rdd.join(otherRdd) |
{(1, "leo"),(2, "jack"),(3, "tom")} {(1, 100), (2, 90), (3, 60), (1, 70), (2, 80), (3, 50)} =>{(1,("leo",100)),(1,("leo",70)),(2, |
RDD[(K, |
同join,也是根据key进行join,只不过相同key的value分别存放到Iterable<value>中 |
rdd.cogroup(otherRdd) |
{(1, "leo"),(2, "jack"),(3, "tom")} {(1, 100), (2, 90), (3, 60), (1, 70), (2, 80), (3, 50)} =>{(1,(["leo"],[100,70])),(2, |
|
常用Action
T reduce(f: (T, T) => T) |
对所有元素进行reduce操作 |
rdd.reduce(_ |
{1, 2, 2, 3, 3, 3} =>14 |
Array[T] |
将RDD中所有元素返回到一个数组里 注意:This method should only |
rdd.collect() |
{1, 2, 3, 3} =>[1, |
Map[K, |
作用于K-V类型的RDD上,作用与collect不同的是collectAsMap函数不包含重复的key,对于重复的key,后面的元素覆盖前面的元素 |
rdd.collectAsMap() |
{ ("leo", 65), ("tom", 50), ("tom", =>{ |
Long count() |
统计RDD 中的元素个数 |
rdd.count() |
{1, 2, 3, 3} =>4 |
Map[T, |
各元素在 RDD 中出现的次数 注意:This method should only To handle |
rdd.countByValue() |
{1, 2, 3, 3} =>Map(1 |
Map[K, |
先根据Key进行分组,再对每组里的value分别进行计数统计 注意:This method should only To handle |
{ ("leo", 65), ("tom", 50), ("tom", 100), =>Map(leo |
|
T first() |
取第一个元素,实质上是调用take(1)实现的 |
rdd.first() |
{3, 2, =>3 |
Array[T] |
从 RDD 中返回前 num 个元素 注意:This method should only |
rdd.take(2) |
{3, 2, 1, 4} =>[3, |
Array[T] 如果没有传递 ord参数,则使用隐式参数,且提供的默认隐式参数为升序排序,可以传递一个自定义的Ordering来覆盖默认提供。 top实现是将Ordering反序后再调用 takeOrdered的:takeOrdered(num)(ord.reverse) |
默认从 RDD 中返回最最大的 num个元素 注意:This method should only |
rdd.top(2) |
{3, 2, 1, 4} =>[4, |
Array[T] 如果没有传递 ord参数,则使用隐式参数,且提供的默认隐式参数为升序排序,可以传递一个自定义的Ordering来覆盖默认提供 |
与top相反,默认取的是前面最小的num个元素 注意:This method should only |
rdd.takeOrdered(2)(myOrdering) |
{3, 2, 1, 4} =>[1, |
T fold(zeroValue: T)(op: (T, T) => T) zeroValue:为每个分区累计的初始值,以及不同分区累计的初始值 e.g., Nil for list concatenation, 0 |
和 reduce() 一 提供初始值。注意:每个分区应用op函数时,都会以zeroValue为初始值进行计算,然后将每个分区的结果合并时,还是会以zeroValue为初始值进行合并计算 |
val arr = Array(1, 2, 3, 4, 5); val rdd = sc.parallelize(arr, 2) //分成两分区[1, println(rdd.fold(10)((v1, v2) |
//处理第一个分区数据 10 + 1 = 11 11 + 2 ===================== //处理第一个分区数据 10 + 3 = 13 13 + 4 17 + 5 ===================== //将各分区汇总起来 10 + 13 = 23 // 汇总时还会使用初始值来作起始 23 + 45 |
U aggregate (zeroValue: U)(seqOp: (U, T) => U, 初始值类型与原始数据类型可以不同,但初始值类型决定了返回值类型 |
与fold一样,计算时需要提供初始值,不同的是,分区的计算函数(seqOp)与分区合并计算函数(combOp)是不同的,但fold分区计算函数与分区合并计算函数是同一函数 |
rdd.fold(5)(_ |
val val println(rdd.aggregate(5)( (v1, (v1, ) 过程与结果与上面的fold函数一样 |
Unit saveAsTextFile(path: String) |
将RDD元素保存到文件中,对每个元素调用toString方法 |
||
Unit foreach(f: T => Unit) |
遍历RDD中的每个元素 |
rdd.foreach(println(_)) |
无 |
comineByKey
def combineByKey[C](
createCombiner: V => C,
mergeValue: (C, V) => C,
mergeCombiners: (C, C) => C,
partitioner: Partitioner,
mapSideCombine: Boolean = true,
serializer: Serializer = null): RDD[(K, C)]
createCombiner:在第一次遇到Key时创建组合器函数,将RDD数据集中的V类型值转换C类型值(V => C),
mergeValue:合并值函数,再次遇到相同的Key时,将createCombiner道理的C类型值与这次传入的V类型值合并成一个C类型值(C,V)=>C
mergeCombiners:合并组合器函数,将C类型值两两合并成一个C类型值
partitioner:使用已有的或自定义的分区函数,默认是HashPartitioner
mapSideCombine:是否在map端进行Combine操作,默认为true
例:统计男性和女生的个数,并以(性别,(名字,名字....),个数)的形式输出
object CombineByKey {
def main(args:
Array[String]) {
val conf = new
SparkConf().setMaster("local").setAppName("combinByKey")
val sc = new SparkContext(conf)
val people = List(("male", "Mobin"), ("male", "Kpop"), ("female", "Lucy"), ("male", "Lufei"), ("female", "Amy"))
val rdd = sc.parallelize(people)
val combinByKeyRDD = rdd.combineByKey(
(x: String) => (List(x), 1),
(peo: (List[String], Int), x: String) => (x :: peo._1, peo._2 + 1),
(sex1: (List[String], Int), sex2: (List[String], Int)) => (sex1._1 ::: sex2._1, sex1._2 + sex2._2))
combinByKeyRDD.foreach(println)
sc.stop()
}
}
输出:
(male,(List(Lufei, Kpop,
Mobin),3))
(female,(List(Amy,
Lucy),2))
计算过程:
Partition1:
K="male" -->
("male","Mobin") -->
createCombiner("Mobin") => peo1 = (
List("Mobin") , 1 )
K="male" -->
("male","Kpop") -->
mergeValue(peo1,"Kpop") => peo2 = (
"Kpop" :: peo1_1 , 1 + 1 ) //Key相同调用mergeValue函数对值进行合并
K="female" -->
("female","Lucy") -->
createCombiner("Lucy") => peo3 = (
List("Lucy") , 1 )
Partition2:
K="male" -->
("male","Lufei") -->
createCombiner("Lufei") => peo4 = ( List("Lufei")
, 1 )
K="female" -->
("female","Amy") -->
createCombiner("Amy") => peo5 = (
List("Amy") , 1 )
Merger Partition:
K="male" --> mergeCombiners(peo2,peo4) =>
(List(Lufei,Kpop,Mobin))
K="female" --> mergeCombiners(peo3,peo5)
=> (List(Amy,Lucy))
附件列表
04、常用RDD操作整理的更多相关文章
- 【linux】工作中linux系统常用命令操作整理
1.Linux如何查看端口 使用lsof(list open files)命令,lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000. 或者使用n ...
- javascript 常用DOM操作整理
.选取了DOM操作中实用并常用的部分,省略了实用但有明显兼容性的部分2.DOM属性和方法的类型归属可能并不完全准确3.某些一般兼容性和特点做了标识(主要是ie8-9上下) 节点类型 节点类型 节点值 ...
- MySQL常用的操作整理
MySQL是一个十分轻便的dbms,轻便.灵活,更适用于中小型数据的存储与架构.MySQL被数以万计的网站采用,从5版本以后,陆续支持了游标.触发器.事务.存储过程等高级应用,这也给MySQL的易用性 ...
- Spark常用RDD操作总结
aggregate 函数原型:aggregate(zeroValue, seqOp, combOp) seqOp相当于Map combOp相当于Reduce zeroValue是seqOp每一个par ...
- ES6常用对象操作整理
const 简单类型数据常量 // const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动.对于简单类型的数据(数值.字符串.布尔值),值就保存在变量指向的那个内存地址,因 ...
- javascript中字符串常用操作整理
javascript中字符串常用操作整理 字符串的操作在js中非常频繁,也非常重要.以往看完书之后都能记得非常清楚,但稍微隔一段时间不用,便会忘得差不多,记性不好是硬伤啊...今天就对字符串的一些常用 ...
- vim程序编辑器---常用操作整理
vim程序编辑器---常用操作整理 移动光标方法 o 在光标行的下一行,进入编辑模式 $ 移动到光标这行,最末尾的地方 G(大写) 移动到文件最末行 :set nu 文件显示行数 :set non ...
- .Net Standard HttpClient封装Htt请求常用操作整理
一.常用Http操作 1.Get请求,有参数,无参数 2.Post 请求,有参数,无参数 3.文件简单下载 修改NetHelper中Post请求方法Bug:请求编码默认UTF8,字符串内存流读取后这是 ...
- 常用js方法整理common.js
项目中常用js方法整理成了common.js var h = {}; h.get = function (url, data, ok, error) { $.ajax({ url: url, data ...
随机推荐
- Codeforces 965E Short Code 启发式合并 (看题解)
Short Code 我的想法是建出字典树, 然后让后面节点最多的点优先向上移到不能移为止, 然后gg. 正确做法是对于当前的节点如果没有被占, 那么从它的子树中选出一个深度最大的点换到当前位置. 用 ...
- 使用sparksql往kafka推送数据
一.相关配置参数 1.同级目录resource文件夹下配置 brokers_list=kafkaxxx02broker01:9092,kafkaxxx02broker02:9092,kafkaxxx0 ...
- Activity的启动
--摘自<android插件化开发指南> 1.AMS管理着四大组件 2.为什么Hook不能在AMS那边?因为AMS属于android系统,android系统可以被Hook,那就是病毒了.四 ...
- AE插入音乐
将音乐文件(如MP3文件)直接拖拽到工程里就可以. 然后添加到合成里. 点击内容预览 ,就自动播放了. 在合成窗口里面,我们可以对于音频文件进行拖动,以及裁剪等操作,但是需要注意的是AE里面不能预览声 ...
- BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】
以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看 重写! 题意: 维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列 splay序列操作裸题 需要 ...
- spy(主席树)
题目链接 题目为某次雅礼集训... 对于\(\max\{a-A_i,\ A_i-a,\ b-B_i,\ B_i-b\}\),令\(x_1=\frac{a+b}{2},\ y_1=\frac{a-b}{ ...
- IDEA安装使用Lombok插件
项目中经常使用bean,entity等类,绝大部分数据类类中都需要get.set.toString.equals和hashCode方法,虽然IDEA开发环境下都有自动生成的快捷方式,但自动生成这些代码 ...
- JavaScript基础笔记(十三)测试和调试
错误处理与测试 一.错误处理 一)try-catch语句 function atest() { try { //可能发生错误的代码 return 0; } catch (error) { //错误处理 ...
- Tomcat安装与环境变量的配置
Tomacat的下载 去Tomcat官网下载,我使用的是apache-tomcat-7.0.78的版本. 安装 下载完成之后,我们解压缩到相应的目录.这里我解压缩到d盘下面 1.然后去配置系统的环 ...
- Python中join 和 split详解(推荐)
http://www.jb51.net/article/87700.htm python join 和 split方法简单的说是:join用来连接字符串,split恰好相反,拆分字符串的. .join ...