---------------------

本节内容:

· 键值对RDD出现背景

· 键值对RDD转化操作实例

· 键值对RDD行动操作实例

· 键值对RDD数据分区

· 参考资料

---------------------

虽然大部分Spark的RDD操作都支持所有种类的对象,但是有少部分特殊的操作只能作用于键值对类型的RDD。这类操作中最常见的就是分布的shuffle操作,比如将元素通过键来分组或聚集计算.因此,键值对RDD也是很多程序不可缺失的一部分.

一、键值对RDD出现背景

mapreduce框架是把数据转化为Key-value,再聚合为key-values的过程,在spark里key-value rdd(pair rdd)同样是最常用的,在每个应用中基本会用到,pair rdd里面的元素是Tuple2,pair rdd的transform函数很多.pari rdd是很多程序的构成要素,因为他们提供了并行性操作各个键或跨节点重新进行分组的操作接口.pair rdd最简单的2种创建方法:

(1)通过map创建实例所示:

---------------------

val line =sc.textFile("/tmp/test/core-site.xml");

val pairs=line.map(x=>(x.split(" ")(0),x));

pairs.foreach(println);

------

说明:

map:读取将读取的每一行用空格的第一行为key,整行内容为value

foreach:循环遍历打印出每个pair

---------------------

(2)直接读取键值对类型的数据

---------------------

val pairrdd = sc.parallelize(List((1,2),(3,4),(3,6)));

pairrdd.foreach(println);

------

说明:

parallelize:从外部数据集读取键值对数据

---------------------

二、键值对RDD转化操作实例

1.例子:reduceByKey/groupByKey/

---------------------

val pairrdd = sc.parallelize(List((1,2),(3,4),(3,6)));

val result=pairrdd.reduceByKey((x,y)=>x+y);

result.foreach(println);

------

说明:

reduceByKey:合并具有相同键的值

---------------------

val pairrdd = sc.parallelize(List((1,2),(3,4),(3,6)));

val result=pairrdd.groupByKey();

result.foreach(println);

------

说明:

groupByKey:将同一个key的值都放到一个列表中,通过ShuffledRDD将每个partition中fetch过来,shuffle机制默认用的是hashShuffle,spark1.1版本引入sorted shuffle,速度更快。shuffle操作后面接着mapPartition()操作,生成MapPartitionRDD.

2.例子:combineByKey/mapvalues

---------------------

val initialScores = Array(("Fred", 88.0), ("Fred", 95.0), ("Fred", 91.0), ("Wilma", 93.0), ("Wilma", 95.0), ("Wilma", 98.0));

val d1 = sc.parallelize(initialScores);

type MVType = (Int, Double) //定义一个元组类型(科目计数器,分数);

d1.combineByKey(

score => (1, score),

(c1: MVType, newScore) => (c1._1 + 1, c1._2 + newScore),

(c1: MVType, c2: MVType) => (c1._1 + c2._1, c1._2 + c2._2)

).map { case (name, (num, socre)) => (name, socre / num) }.collect().foreach(println);

------

说明:

combineByKey:

a .score => (1, score),我们把分数作为参数,并返回了附加的元组类型。 以"Fred"为列,当前其分数为88.0 =>(1,88.0)  1表示当前科目的计数器,此时只有一个科目

b.(c1: MVType, newScore) => (c1._1 + 1, c1._2 + newScore),注意这里的c1就是createCombiner初始化得到的(1,88.0)。在一个分区内,我们又碰到了"Fred"的一个新的分数91.0。当然我们要把之前的科目分数和当前的分数加起来即c1._2 + newScore,然后把科目计算器加1即c1._1 + 1

c.(c1: MVType, c2: MVType) => (c1._1 + c2._1, c1._2 + c2._2),注意"Fred"可能是个学霸,他选修的科目可能过多而分散在不同的分区中。所有的分区都进行mergeValue后,接下来就是对分区间进行合并了,分区间科目数和科目数相加分数和分数相加就得到了总分和总科目数

结果:

(Wilma,95.33333333333333)

(Fred,91.33333333333333)

---------------------

val pairrdd = sc.parallelize(List((1,2),(3,4),(3,6)));

val result=pairrdd.mapValues(x=>x+1);

result.foreach(println);

------

说明:

mapValues:对每个键的值应用一个函数而不改变键的内容

---------------------

3.例子:flatMapValues/keys/values/sotByKey

---------------------

val pairrdd = sc.parallelize(List((1,2),(3,4),(3,6)));

val result=pairrdd.flatMapValues(x=>(x to 5));

result.foreach(println);

------

说明:

flatMapValues:对每个值应用一个返回迭代器函数,然后对返回的每个值都生成一个对应原键的键值对记录,通常用于符号化.

结果:

(1,2)

(1,3)

(1,4)

(1,5)

(3,4)

(3,5)

---------------------

val pairrdd = sc.parallelize(List((1,2),(3,4),(3,6)));

val result=pairrdd.keys;//scala不要使用括号

result.foreach(println);

------

说明:

keys:对返回一个仅包含键的RDD.

---------------------

val pairrdd = sc.parallelize(List((1,2),(3,4),(3,6)));

val result=pairrdd.values;//scala不要使用括号

result.foreach(println);

------

说明:

values:对返回一个仅包含键的RDD.

---------------------

val pairrdd = sc.parallelize(List((1,2),(3,4),(3,6)));

val result=pairrdd.sortByKey(false);

result.foreach(println);

------

说明:

sortByKey:对返回一个根据键排序的RDD.默认不填为true,ascending升序方式

---------------------

4.例子:subtractByKey/join/leftOuterJoin/rightOuterJoin/coGroup

---------------------

val rdd= sc.parallelize(List((1,2),(3,4),(3,6)));

val other= sc.parallelize(List((3,6)));

val result=rdd.subtract(other);

result.foreach(println);

------

说明:删除rdd RDD 键与other RDD中的键相同的元素.

subtract:对返回一个根据键排序的RDD.

结果:

(3,4)

(1,2)

---------------------

val rdd= sc.parallelize(List((1,2),(3,4),(3,6)));

val other= sc.parallelize(List((3,9)));

val result=rdd.join(other);

result.foreach(println);

------

说明:

join:对2个RDD进行内连接,key相同的进行操作

结果:

(3,(4,9))

(3,(6,9))

---------------------

val rdd= sc.parallelize(List((1,2),(3,4),(3,6)));

val other= sc.parallelize(List((3,9)));

val result=rdd.leftOuterJoin(other);

result.foreach(println);

------

说明:

leftOuterJoin:左外连接,对2个rdd进行连接操作,确保左边(rdd RDD)的键一定存在

结果:

(1,(2,none))

(3,(4,some(9)))

(3,(6,some(9)))

---------------------

val rdd= sc.parallelize(List((1,2),(3,4),(3,6)));

val other= sc.parallelize(List((3,9)));

val result=rdd.rightOuterJoin(other);

result.foreach(println);

------

说明:

rightOuterJoin:右外连接,对2个rdd进行连接操作,确保右边(rdd RDD)的键一定存在

结果:

(3,(some(4),9))

(3,(some(6),9))

---------------------

val rdd= sc.parallelize(List((1,2),(3,4),(3,6)));

val other= sc.parallelize(List((3,9)));

val result=rdd.cogroup(other);

result.foreach(println);

------

说明:

cogroup:将2个RDD拥有相同键的数据分组到一起

结果:

(1,(compactBuffer(2),compactBuffer()))

(3,(compactBuffer(4,6),compactBuffer(9)))

---------------------

三、键值对RDD行动操作实例

和转换操作一样,所有基础RDD支持的传统行动操作也都在pair RDD上可用,除此之外,pair RDD还提供了一些额外的行动操作。

1.例子:countByKey/collectAsMap/lookup(key)

---------------------

val rdd= sc.parallelize(List((1,2),(3,4),(3,6)));

val result=rdd.countByKey();

result.foreach(println);

------

说明:

countByKey:对每个键对应的元素分别计数

结果:

(1,1)

(3,2)

---------------------

val rdd= sc.parallelize(List((1,2),(3,4),(3,6)));

val result=rdd.collectAsMap();

result.foreach(println);

------

说明:

collectAsMap:从结果我们可以看出,如果RDD中同一个Key中存在多个Value,那么后面的Value将会把前面的Value覆盖,最终得到的结果就是Key唯一,而且对应一个Value,《Spark快速大数据分析》第52页给出的结果是不对的。

结果:

(1,2)

(3,6)

---------------------

val rdd= sc.parallelize(List((1,2),(3,4),(3,6)));

val result=rdd.lookup(3);

result.foreach(println);

------

说明:

lookup:返回给定键对应的所有值

结果:

4

6

---------------------

三、参考资料

1.http://blog.csdn.net/gamer_gyt/article/details/51747783,Spark 的键值对(pair RDD)操作,Scala实现

2.http://blog.csdn.net/jiangpeng59/article/details/52538254,Spark核心RDD:combineByKey函数详解

【Spark 深入学习 07】RDD编程之旅基础篇03-键值对RDD的更多相关文章

  1. 【spark 深入学习 05】RDD编程之旅基础篇-01

    ---------------- 本节内容 1.RDD的工作流程 2.WordCount解说  · shell版本WordCount  · java版本WordCount -------------- ...

  2. 【spark 深入学习 06】RDD编程之旅基础篇02-Spaek shell

    --------------------- 本节内容: · Spark转换 RDD操作实例 · Spark行动 RDD操作实例 · 参考资料 --------------------- 关于学习编程方 ...

  3. 5.2 RDD编程---键值对RDD

    一.键值对RDD的创建 1.从文件中加载 2.通过并行集合(数组)创建RDD 二.常用的键值对RDD转换操作 1.reduceByKey(func) 功能:使用func函数合并具有相同键的值 2.gr ...

  4. Spark 键值对RDD操作

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

  5. ESP8266开发之旅 基础篇① 走进ESP8266的世界

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  6. ESP8266开发之旅 基础篇③ ESP8266与Arduino的开发说明

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  7. ESP8266开发之旅 基础篇④ ESP8266与EEPROM

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  8. ESP8266开发之旅 基础篇② 如何安装ESP8266的Arduino开发环境

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  9. ESP8266开发之旅 基础篇⑥ Ticker——ESP8266定时库

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

随机推荐

  1. Scrapy爬虫学习笔记 - windows \ linux下搭建开发环境1

    一.pycharm的安装和简单使用                                   二.mysql和navicat的安装和使用    三.windows和linux下安装pytho ...

  2. Unity3d和Android之间互相调用

    摘抄博客 Unity3d Android SDK接入解析(一)Unity3d 与 Android之间的互相调用,一共四章,一定要看完 No1: 总体来说Unity3d与Android之间的互相调用,是 ...

  3. jackson实现java对象转支付宝/微信模板消息

    一.支付宝消息模板大致长这样 { "to_user_id": "", "telephone": "xxxxx", &qu ...

  4. CentOS 6.4在运行XFS时系统crash的bug分析

    最近有一台CentOS 6.4的服务器发生多次crash,kernel version 是Linux 2.6.32-431.29.2.el6.x86_64.从vmcore-dmesg日志内容及cras ...

  5. Java设计模式从精通到入门三 策略模式

    介绍 我尽量用最少的语言解释总结: Java23种设计模式之一,属于行为型模式.一个类的行为或者算法可以在运行时更改,策略对象改变context对象执行算法. 应用实例: ​ 以周瑜赔了夫人又折兵的例 ...

  6. 在网站中使用Bing Translator插件翻译文章。

    前一阵子给项目增加了翻译的功能,用的是Bing Translator Widget,今天看见有个兄弟写自定义自己的博客,我就尝试着把这个插件加到了自己的博客中.还真的好用.大家先看下效果,觉得好的请继 ...

  7. SQLite中的SELECT子句使用通配符

    SQLite中的SELECT子句使用通配符 在SELECT子句中支持两个通配符,分别为*和table_name.*.其中,*通配符会将FROM子句中每个源表的所有用户定义的列进行输出.例如,下面的SQ ...

  8. C# 运行中 Lua 语言脚本

    这里就不介绍Lua语言了,使用挺广的一种脚本语言.自行百度. 第一步 使用 Nuget 安装引用 VikingErik.LuaInterface. 第二步 添加 Using using LuaInte ...

  9. 10.24 正睿停课训练 Day8 AM

    目录 2018.10.24 正睿停课训练 Day8 AM A 棒棒糖(组合) B 彩虹糖(思路 博弈) C 泡泡糖(DP) 考试代码 A B C 2018.10.24 正睿停课训练 Day8 AM 期 ...

  10. Python图形编程探索系列-04-网上图片与标签组件的结合

    跳转到自己的博客 任务设定 任务:从网上找到一张图片,然后将其显示在标签上? 网上图片网站:http://pic.58pic.com/58pic/17/56/38/52w58PICtER_1024.j ...