RDD的详解



RDD:弹性分布式数据集,是Spark中最基本的数据抽象,用来表示分布式集合,支持分布式操作!

RDD的创建

RDD中的数据可以来源于2个地方:本地集合或外部数据源

RDD操作

分类

转换算子

Map

···

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Demo03Map {

def main(args: Array[String]): Unit = {

val conf: SparkConf = new SparkConf()

conf.setAppName("Demo03Map").setMaster("local")

val sc: SparkContext = new SparkContext(conf)

//读取文件数据

val linesRDD: RDD[String] = sc.textFile("spark/data/words.txt")

//对数据进行扁平化处理

val flatRDD: RDD[String] = linesRDD.flatMap(_.split(","))

  1. //按照单词分组
  2. val groupRDD: RDD[(String, Iterable[String])] = flatRDD.groupBy(w => w)
  3. //聚合
  4. val wordsRDD: RDD[String] = groupRDD.map(kv => {
  5. val key: String = kv._1
  6. val words: Iterable[String] = kv._2
  7. key + "," + words.size
  8. })
  9. //分组+聚合
  10. val mapRDD1: RDD[(String, Int)] = flatRDD.map((_, 1))
  11. val words1: RDD[(String, Int)] = mapRDD1.reduceByKey(_ + _)
  12. ////分组+聚合
  13. val mapRDD2: RDD[(String, Int)] = flatRDD.map((_, 1))
  14. val words2: RDD[(String, Iterable[Int])] = mapRDD2.groupByKey()
  15. val wordSum: RDD[(String, Int)] = words2.mapValues(_.size)
  16. wordSum.foreach(println)
  17. //输出
  18. wordsRDD.foreach(println)
  19. words1.foreach(println)

}

}

flatMap(数据扁平化处理)

  1. import org.apache.spark.rdd.RDD
  2. import org.apache.spark.{SparkConf, SparkContext}
  3. object Demo04FlatMap {
  4. def main(args: Array[String]): Unit = {
  5. val conf: SparkConf = new SparkConf().setAppName("Demo04FlatMap").setMaster("local")
  6. val sc: SparkContext = new SparkContext(conf)
  7. val linesRDD: RDD[String] = sc.parallelize(List("java,scala,python", "map,java,scala"))
  8. //扁平化处理
  9. val flatRDD: RDD[String] = linesRDD.flatMap(_.split(","))
  10. flatRDD.foreach(println)
  11. }
  12. }
  13. Mappartitions
  14. ### map和mapPartitions区别
  15. 1map:每次处理一条数据
  16. 2mapPartitions:每次处理一个分区数据

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Demo05MapPartition {

def main(args: Array[String]): Unit = {

val conf: SparkConf = new SparkConf().setAppName("Demo05MapPartition").setMaster("local")

val sc: SparkContext = new SparkContext(conf)

val stuRDD: RDD[String] = sc.textFile("spark/data/words.txt",3)

stuRDD.mapPartitions(rdd => {

println("map partition")

// 按分区去处理数据

rdd.map(line => line.split(",")(1))

}).foreach(println)

}

}

fliter 过滤

  1. import org.apache.spark.rdd.RDD
  2. import org.apache.spark.{SparkConf, SparkContext}
  3. object Demo06Filter {
  4. def main(args: Array[String]): Unit = {
  5. val conf: SparkConf = new SparkConf().setAppName("Demo05MapPartition").setMaster("local")
  6. val sc: SparkContext = new SparkContext(conf)
  7. val linesRDD: RDD[Int] = sc.parallelize(List(1, 2, 3, 4, 5))
  8. //过滤,转换算子
  9. linesRDD.filter(kv => {
  10. kv % 2 == 1
  11. }).foreach(println)
  12. }
  13. }
  14. sample 取样

import org.apache.spark.{SparkConf, SparkContext}

import org.apache.spark.rdd.RDD

object Demo07Sample {

def main(args: Array[String]): Unit = {

val conf: SparkConf = new SparkConf().setAppName("Demo05MapPartition").setMaster("local")

val sc: SparkContext = new SparkContext(conf)

/**

* sample:对数据取样

* withReplacement 有无放回

* fraction 抽样比例

* withReplacement:表示抽出样本后是否在放回去,true表示会放回去

* 这也就意味着抽出的样本可能有重复

* fraction :抽出多少,这是一个double类型的参数,0-1之间,eg:0.3表示抽出30%

*/

val stuRDD: RDD[String] = sc.textFile("spark/data/students.txt",3)

stuRDD.sample(withReplacement = true,0.1).foreach(println)

}

}

union 将相同结结构的数据连接到一起

  1. import org.apache.spark.rdd.RDD
  2. import org.apache.spark.{SparkConf, SparkContext}
  3. object Demo08Union {
  4. def main(args: Array[String]): Unit = {
  5. val conf: SparkConf = new SparkConf().setAppName("Demo05MapPartition").setMaster("local")
  6. val sc: SparkContext = new SparkContext(conf)
  7. /**union
  8. * 将两个相同结构的数据连接在一起
  9. */
  10. val lineRDD1: RDD[String] = sc.parallelize(List("java,scala", "data,python"))
  11. val lineRDD2: RDD[String] = sc.parallelize(List("spark,scala", "java,python"))
  12. println(lineRDD1.getNumPartitions)
  13. val unionRDD: RDD[String] = lineRDD1.union(lineRDD2)
  14. println(unionRDD.getNumPartitions)
  15. unionRDD.foreach(println)
  16. }
  17. }
  18. mappatitionWIthindex
  1. //mapPartitionsWithIndex也是一个转换算子
  2. // 会在处理每一个分区的时候获得一个index
  3. //可以选择的执行的分区
  4. stuRDD.mapPartitionsWithIndex((index, rdd) => {
  5. println("当前遍历的分区:" + index)
  6. // 按分区去处理数据
  7. rdd.map(line => line.split(",")(1))
  8. }).foreach(println)

join 将数据按照相同key进行关联(数据必须是(K,V))

  1. import java.io
  2. import org.apache.spark.rdd.RDD
  3. import org.apache.spark.{SparkConf, SparkContext}
  4. object Demo09Join {
  5. def main(args: Array[String]): Unit = {
  6. val conf: SparkConf = new SparkConf().setAppName("Demo05MapPartition").setMaster("local")
  7. val sc: SparkContext = new SparkContext(conf)
  8. // 构建K-V格式的RDD
  9. val tuple2RDD1: RDD[(String, String)] = sc.parallelize(List(("001", "张三"), "002" -> "小红", "003" -> "小明"))
  10. val tuple2RDD2: RDD[(String, Int)] = sc.parallelize(List(("001", 20), "002" -> 22, "003" -> 21))
  11. val tuple2RDD3: RDD[(String, String)] = sc.parallelize(List(("001", "男"), "002" -> "女"))
  12. //将文件进行join
  13. val joinRDD: RDD[(String, (String, Int))] = tuple2RDD1.join(tuple2RDD2)
  14. joinRDD.map(kv => {
  15. val i: String = kv._1
  16. val j: String = kv._2._1
  17. val k: Int = kv._2._2
  18. i + "," + j + "," + k
  19. }).foreach(println)
  20. //第二种方式
  21. joinRDD.map {
  22. case (id: String, (name: String, age: Int)) => id + "*" + name + "*" + age
  23. }.foreach(println)
  24. val leftJoinRDD: RDD[(String, (String, Option[String]))] = tuple2RDD1.leftOuterJoin(tuple2RDD3)
  25. leftJoinRDD.map {
  26. //存在关联
  27. case (id: String, (name: String, Some(gender))) =>
  28. id + "*" + name + "*" + gender
  29. //不存在关联
  30. case (id: String, (name: String, None)) =>
  31. id + "*" + name + "*" + "_"
  32. }
  33. }
  34. }
  35. groupByKey kv格式的数据进行key的聚合

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Demo10GroupByKey {

def main(args: Array[String]): Unit = {

val conf: SparkConf = new SparkConf().setAppName("Demo10GroupByKey").setMaster("local")

val sc: SparkContext = new SparkContext(conf)

/**

* groupBy 指定分组的字段进行分组

*/

  1. // 统计班级人数
  2. val linesRDD: RDD[String] = sc.textFile("spark/data/students.txt")
  3. linesRDD.groupBy(word => word.split(",")(4))
  4. .map(kv => {
  5. val key = kv._1
  6. val wordsCnt = kv._2.size
  7. key + "," + wordsCnt
  8. }).foreach(println)
  9. val linesMap: RDD[(String, String)] = linesRDD.map(lines => (lines.split(",")(4), lines))
  10. //按照key进行分组
  11. linesMap.groupByKey()
  12. .map(lines=>{
  13. val key = lines._1
  14. val wordsCnt: Int = lines._2.size
  15. key+","+wordsCnt
  16. }).foreach(println)

}

}

ReduceByKey

reduceByKey 需要接收一个聚合函数

首先会对数据按key分组 然后在组内进行聚合(一般是加和,也可以是Max、Min之类的操作)

相当于 MR 中的combiner

可以在Map端进行预聚合,减少shuffle过程需要传输的数据量,以此提高效率

相对于groupByKey来说,效率更高,但功能更弱

幂等操作

y = f(x) = f(y) = f(f(x))

reducebyKey与groupbykey的区别

reduceByKey:具有预聚合操作

groupByKey:没有预聚合

在不影响业务逻辑的前提下,优先采用reduceByKey。

  1. import org.apache.spark.rdd.RDD
  2. import org.apache.spark.{SparkConf, SparkContext}
  3. object Demo11ReduceByKey {
  4. def main(args: Array[String]): Unit = {
  5. val conf: SparkConf = new SparkConf().setAppName("Demo11ReduceByKey").setMaster("local")
  6. val sc: SparkContext = new SparkContext(conf)
  7. val linesRDD: RDD[String] = sc.textFile("spark/data/students.txt")
  8. //统计班级人数
  9. linesRDD.map(lines => (lines.split(",")(4), lines))
  10. .groupByKey()
  11. .map(kv => {
  12. val key = kv._1
  13. val cnt = kv._2.size
  14. key + "" + cnt
  15. }).foreach(println)
  16. //ReduceByKey
  17. /**
  18. * reduceByKey 需要接收一个聚合函数
  19. * 首先会对数据按key分组 然后在组内进行聚合(一般是加和,也可以是Max、Min之类的操作)
  20. * 相当于 MR 中的combiner
  21. * 可以在Map端进行预聚合,减少shuffle过程需要传输的数据量,以此提高效率
  22. * 相对于groupByKey来说,效率更高,但功能更弱
  23. * 幂等操作
  24. * y = f(x) = f(y) = f(f(x))
  25. */
  26. linesRDD.map(lines=>(lines.split(",")(4),1))
  27. .reduceByKey(_+_)
  28. .foreach(println)
  29. }
  30. }
  31. sort 排序,默认升序

import org.apache.spark.{SparkConf, SparkContext}

import org.apache.spark.rdd.RDD

object Demo12Sort {

def main(args: Array[String]): Unit = {

val conf: SparkConf = new SparkConf().setAppName("Demo12Sort").setMaster("local")

val sc: SparkContext = new SparkContext(conf)

val linesRDD: RDD[String] = sc.textFile("spark/data/students.txt")

  1. /**
  2. * sortBy 转换算子
  3. * 指定按什么排序 默认升序
  4. *
  5. * sortByKey 转换算子
  6. * 需要作用在KV格式的RDD上,直接按key排序 默认升序
  7. */
  8. linesRDD.sortBy(lines => lines.split(",")(2), ascending = false) //按照年纪降序
  9. .take(10) //转换算子打印十行
  10. .foreach(println)
  11. val mapRDD: RDD[(String, String)] = linesRDD.map(l => (l.split(",")(2), l))
  12. mapRDD.sortByKey(ascending = false)
  13. .take(10)
  14. .foreach(println)

}

}

Mapvalue

  1. import org.apache.spark.rdd.RDD
  2. import org.apache.spark.{SparkConf, SparkContext}
  3. object Demo13MapValue {
  4. def main(args: Array[String]): Unit = {
  5. /**
  6. * mapValues 转换算子
  7. * 需要作用在K—V格式的RDD上
  8. * 传入一个函数f
  9. * 将RDD的每一条数据的value传给函数f,key保持不变
  10. * 数据规模也不会改变
  11. */
  12. val conf: SparkConf = new SparkConf().setAppName("Demo13MapValue").setMaster("local")
  13. val sc: SparkContext = new SparkContext(conf)
  14. val linesRDD: RDD[(String, Int)] = sc.parallelize(List(("zs", 10), ("zzw", 34), ("lm", 18)))
  15. linesRDD.mapValues(lines=>lines*2)
  16. .foreach(println)
  17. }
  18. ### 行为算子
  19. ![](https://img2020.cnblogs.com/blog/2506444/202111/2506444-20211110144134743-1836525955.png)

RDD的详解、创建及其操作的更多相关文章

  1. ASP.NET MVC Filters 4种默认过滤器的使用【附示例】 数据库常见死锁原因及处理 .NET源码中的链表 多线程下C#如何保证线程安全? .net实现支付宝在线支付 彻头彻尾理解单例模式与多线程 App.Config详解及读写操作 判断客户端是iOS还是Android,判断是不是在微信浏览器打开

    ASP.NET MVC Filters 4种默认过滤器的使用[附示例]   过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响 ...

  2. App.Config详解及读写操作

    App.Config详解及读写操作   App.Config详解 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而 ...

  3. Spark RDD API详解(一) Map和Reduce

    RDD是什么? RDD是Spark中的抽象数据结构类型,任何数据在Spark中都被表示为RDD.从编程的角度来看,RDD可以简单看成是一个数组.和普通数组的区别是,RDD中的数据是分区存储的,这样不同 ...

  4. [转载]App.Config详解及读写操作

    App.Config详解 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而不必重编译应用程序.配置文件的根节点是c ...

  5. (转)App.Config详解及读写操作

    App.Config详解 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而不必重编译应用程序.配置文件的根节点是c ...

  6. Spark RDD API详解之:Map和Reduce

    RDD是什么? RDD是Spark中的抽象数据结构类型,任何数据在Spark中都被表示为RDD.从编程的角度来看, RDD可以简单看成是一个数组.和普通数组的区别是,RDD中的数据是分区存储的,这样不 ...

  7. mysql详解常用命令操作,利用SQL语句创建数据表—增删改查

    关系型数据库的核心内容是 关系 即 二维表 MYSQL的启动和连接show variables; [所有的变量] 1服务端启动 查看服务状态 sudo /etc/init.d/mysql status ...

  8. python数据库操作常用功能使用详解(创建表/插入数据/获取数据)

    实例1.取得MYSQL版本 复制代码 代码如下: # -*- coding: UTF-8 -*-#安装MYSQL DB for pythonimport MySQLdb as mdbcon = Non ...

  9. 版本控制之五:SVN trunk(主线) branch(分支) tag(标记) 用法详解和详细操作步骤(转)

    使用场景: 假如你的项目(这里指的是手机客户端项目)的某个版本(例如1.0版本)已经完成开发.测试并已经上线了,接下来接到新的需求,新需求的开发需要修改多个文件中的代码,当需求已经开始开发一段时间的时 ...

随机推荐

  1. Spotlight监控工具的使用

    Spotlight下载地址:http://spotlight-on-unix.software.informer.com/download/#downloading Spotlight是Quest公司 ...

  2. 《手把手教你》系列技巧篇(二十七)-java+ selenium自动化测试- quit和close的区别(详解教程)

    1.简介 尽管有的小伙伴或者童鞋们觉得很简单,不就是关闭退出浏览器,但是宏哥还是把两个方法的区别说一下,不然遇到坑后根本不会想到是这里的问题. 2.源码 本文介绍webdriver中关于浏览器退出操作 ...

  3. HTML 网页开发、CSS 基础语法——九.CSS概述

    1.产生背景 从HTML的答案盛开时,样式就以各种形式存在,最初的HTML只i包含很少的显示属性.随着HTML的成长为了满足页面设计者的要求,HTML添加了许多显示功能,随着功能的增加HTML页面变得 ...

  4. WPF进阶技巧和实战05-样式与行为

    样式(style)是组织和重用格式化选项的重要工具.创建一系列封装某些细节的样式,然后通过属性来应用样式. 行为(behavior)是一款重用用户界面代码更有挑战性的工具.基本思想是:使用行为封装一些 ...

  5. String(char[] value, boolean share) {

    记录一下今天被蠢到 1. 在观察StringBuffer类的toString方法时,发现了个没见过的方法 return new String(toStringCache, true); @Overri ...

  6. 一款简单实用的串口通讯框架(SerialIo)

    前言 大龄程序员失业状态,前几天面试了一家与医疗设备为主的公司并录取:因该单位涉及串口通讯方面技术,自己曾做过通讯相关的一些项目,涉及Socket的较多,也使用SuperSocket做过一些项目,入职 ...

  7. 11.4.4 LVS-Fullnat

    lvs-fullnat(双向转换) 通过请求报文的源地址为DIP,目标为RIP来实现转发:对于响应报文而言,修改源地址为VIP,目标地址为CIP来实现转发: CIP --> DIP VIP -- ...

  8. 2020.4.6--UCF Local Programming Contest 2017的正式赛

    Problem A : Electric Bill 题目大意:进行电量分级制收费,1000kwh及以下一档收费,1000kwh以上按另一档收费,给出每个人的电量总额,问每人应支付多少钱. 思路:基础i ...

  9. RA-28000 账号被锁定的解决办法

    ORA-28000 账号被锁定的解决办法 错误场景:当使用sqlplus进行登录时报错:ORA-28000 账号被锁定.错误原因:由于oracle 11g 在默认在default概要文件中设置了密码最 ...

  10. 从C过渡到C++需要了解的“新特性”

    第一个C++程序 #include <iostream> using namespace std; //编译指令 int main() { cout << "Hell ...