1、 map(func)

作用: 返回一个新的 RDD, 该 RDD 是由原 RDD 的每个元素经过函数转换后的值而组成. 就是对 RDD 中的数据做转换.

创建一个包含1-10的的 RDD,然后将每个元素*2形成新的 RDD

scala > val rdd1 = sc.parallelize(1 to 10)
// 得到一个新的 RDD, 但是这个 RDD 中的元素并不是立即计算出来的
scala> val rdd2 = rdd1.map(_ * 2)

2、mapPartitions(func)

作用: 类似于map(func), 但是是独立在每个分区上运行.所以:Iterator<T> => Iterator<U>

假设有N个元素,有M个分区,那么map的函数的将被调用N次,而mapPartitions被调用M次,一个函数一次处理所有分区。

scala > val rdd1 = sc.parallelize(1 to 10)
// 得到一个新的 RDD, 但是这个 RDD 中的元素并不是立即计算出来的
scala> val rdd2 = rdd1.mapPartitions(_ * 2)
scala> rdd2.collect
res9: Array[Int] = Array(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

3、mapPartitionsWithIndex(func)

作用: 和mapPartitions(func)类似. 但是会给func多提供一个Int值来表示分区的索引. 所以func的类型是:

(Int, Iterator<T>)=> Iterator<U>

scala> val rdd1 = sc.parallelize(Array(10,20,30,40,50,60))
scala> val rdd2 = rdd1.mapPartitionsWithIndex((index, items) => items.map((index, _)))
scala> res2.collect
res9: Array[(Int, Int)] = Array((0,10), (0,20), (0,30), (1,40), (1,50), (1,60))
(1)确定分区数
override def defaultParallelism(): Int =
scheduler.conf.getInt("spark.default.parallelism", totalCores)
(2)对元素分区
// length: RDD 中数据的长度  numSlices: 分区数
def positions(length: Long, numSlices: Int): Iterator[(Int, Int)] = {
(0 until numSlices).iterator.map { i =>
val start = ((i * length) / numSlices).toInt
val end = (((i + 1) * length) / numSlices).toInt
(start, end)
}
}
seq match {
case r: Range => case nr: NumericRange[_] => case _ =>
val array = seq.toArray // To prevent O(n^2) operations for List etc
positions(array.length, numSlices).map { case (start, end) =>
array.slice(start, end).toSeq
}.toSeq
}

5、map和mapPartitions的区别

(1) map():每次处理一条数据

(2) mapPartition():每次处理一个分区的数据,这个分区的数据处理完后,原 RDD 中该分区的数据才能释放,可能导致 OOM

6、flatMap(func)

作用: 类似于map,但是每一个输入元素可以被映射为 0 个输出元素(所以func应该返回一个序列,而不是单一元素 T => TraversableOnce[U])

创建一个元素为 1-5 的RDD,运用 flatMap创建一个新的 RDD,新的 RDD 为原 RDD 每个元素的 平方和三次方 来组成 1,1,4,8,9,27..

scala> val rdd1 = sc.parallelize(Array(1,2,3,4,5))
scala> val rdd2 =rdd1.flatMap(x => Array(x * x, x * x * x))
scala> rdd2.collect
res14: Array[Int] = Array(1, 1, 4, 8, 9, 27, 16, 64, 25, 125)

7、glom()

作用: 将每一个分区的元素合并成一个数组,形成新的 RDD 类型是RDD[Array[T]]

scala> var rdd1 = sc.parallelize(Array(10,20,30,40,50,60), 4)
scala> rdd1.glom.collect
res2: Array[Array[Int]] = Array(Array(10), Array(20, 30), Array(40), Array(50, 60))

8、groupBy(func)

作用:按照func的返回值进行分组.

func返回值作为 key, 对应的值放入一个迭代器中. 返回的 RDD: RDD[(K,Iterable[T])

创建一个 RDD,按照元素的奇偶性进行分组

scala> val rdd1 = sc.makeRDD(Array(1, 3, 4, 20, 4, 5, 8))
scala> val rdd2 = rdd1.groupBy(x => if(x % 2 == 1) "odd" else "even")
scala> rdd2.collect
res5: Array[(String, Iterable[Int])] = Array((even,CompactBuffer(4, 20, 4, 8)), (odd,CompactBuffer(1, 3, 5)))

9、filter(func)

作用: 过滤. 返回一个新的 RDD 是由func的返回值为true的那些元素组成

创建一个 RDD(由字符串组成),过滤出一个新 RDD(包含“xiao”子串)

scala> val rdd1 = sc.parallelize(Array("xiaoli", "laoli", "laowang", "xiaocang", "xiaojing", "xiaokong"))
scala> val rdd2 = rdd1.filter(_.contains("xiao"))
scala> rdd2.collect
res4: Array[String] = Array(xiaoli, xiaocang, xiaojing, xiaokong)

10、sample(withReplacement,fraction,seed)

作用

(1)以指定的随机种子随机抽样出比例为fraction的数据,(抽取到的数量是: size * fraction). 需要注意的是得到的结果并不能保证准确的比例

(2)withReplacement表示是抽出的数据是否放回

​ true为有放回的抽样

​ false为无放回的抽样

true放回表示数据有可能会被重复抽取到,是 true, 则fraction大于等于0就可以了

false 则不可能重复抽取到. 如果是false, 则fraction必须是:[0,1]

(3)seed用于指定随机数生成器种子。 一般用默认的, 或者传入当前的时间戳

(4)不放回抽样

scala> val rdd1 = sc.parallelize(1 to 10)

scala> rdd1.sample(false, 0.5).collect
res15: Array[Int] = Array(1, 3, 4, 7)

(5)放回抽样

scala> val rdd1 = sc.parallelize(1 to 10)
scala> rdd1.sample(true, 2).collect
res25: Array[Int] = Array(1, 1, 2, 3, 3, 4, 4, 5, 5, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9)

11、distinct([numTasks])

作用:对 RDD 中元素执行去重操作. 参数表示任务的数量.默认值和分区数保持一致.

scala> val rdd1 = sc.parallelize(Array(10,10,2,5,3,5,3,6,9,1))

scala> rdd1.distinct().collect
res29: Array[Int] = Array(6, 10, 2, 1, 3, 9, 5)

本质上是reduceByKey

  /**
* Return a new RDD containing the distinct elements in this RDD.
*/
def distinct(numPartitions: Int)(implicit ord: Ordering[T] = null): RDD[T] = withScope {
map(x => (x, null)).reduceByKey((x, y) => x, numPartitions).map(_._1)
}

12 、coalesce(numPartitions)

作用: 缩减分区数到指定的数量,用于大数据集过滤后,提高小数据集的执行效率。

scala> val rdd1 = sc.parallelize(0 to 100, 5)

scala> rdd1.partitions.length
res3: Int = 5 // 减少分区的数量至 2
scala>val rdd2= rdd1.coalesce(2) scala> rdd2.partitions.length
res4: Int = 2
注意:

第二个参数表示是否shuffle, **如果不传或者传入的为false,** 则表示不进行shuffer, 此时分区数减少有效, 增加分区数无效.

13、repartition(numPartitions)

作用: 根据新的分区数, 重新 shuffle 所有的数据, 这个操作总会通过网络(跨分区操作).

新的分区数相比以前可以多, 也可以少,一般用于增加分区,语义清晰

scala> val rdd1 = sc.parallelize(0 to 100, 5)

scala> val rdd2 = rdd1.repartition(3)

scala> res2.partitions.length
res4: Int = 3 scala> val rdd3 = rdd1.repartition(10) scala> rdd3.partitions.length
res5: Int = 10
coalasce和repartition的区别

(1) coalesce重新分区,可以选择是否进行shuffle过程。由参数shuffle: Boolean = false/true决定。

(2)repartition实际上是调用的的coalesce,进行shuffle

def repartition(numPartitions: Int)(implicit ord: Ordering[T] = null): RDD[T] = withScope {
coalesce(numPartitions, shuffle = true)
}

(3)如果是减少分区, 尽量避免shuffle

14、sortBy(func,[ascending],[numTasks])

作用: 使用func先对数据进行处理,按照处理后结果排序,默认为正序

scala> val rdd1 = sc.parallelize(Array(1,3,4,10,4,6,9,20,30,16))

scala> rdd1.sortBy(x => x).collect
res17: Array[Int] = Array(1, 3, 4, 4, 6, 9, 10, 16, 20, 30) scala> rdd1.sortBy(x => x, true).collect
res18: Array[Int] = Array(1, 3, 4, 4, 6, 9, 10, 16, 20, 30) // 不用正序
scala> rdd1.sortBy(x => x, false).collect
res19: Array[Int] = Array(30, 20, 16, 10, 9, 6, 4, 4, 3, 1)

15、pipe(command,[envVars])

作用: 管道,针对每个分区,把 RDD 中的每个数据通过管道传递给shell命令或脚本,返回输出的RDD。

一个分区执行一次这个命令. 如果只有一个分区, 则执行一次命令.

注意:

脚本要放在 worker 节点可以访问到的位置

(1)创建一个脚本文件pipe.sh

echo "hello"
while read line;do
echo ">>>"$line
done

(2)创建只有 1 个分区的RDD

scala> val rdd1 = sc.parallelize(Array(10,20,30,40), 1)

scala> rdd1.pipe("./pipe.sh").collect
res1: Array[String] = Array(hello, >>>10, >>>20, >>>30, >>>40)

(3)创建有 2 个分区的 RDD

scala> val rdd1 = sc.parallelize(Array(10,20,30,40), 2)

scala> rdd1.pipe("./pipe.sh").collect
res2: Array[String] = Array(hello, >>>10, >>>20, hello, >>>30, >>>40)

每个分区执行一次脚本, 但是每个元素算是标准输入中的一行

Spark-Core RDD转换算子-Value型的更多相关文章

  1. Spark-Core RDD转换算子-kv型

    大多数的 Spark 操作可以用在任意类型的 RDD 上, 但是有一些比较特殊的操作只能用在key-value类型的 RDD 上. 这些特殊操作大多都涉及到 shuffle 操作, 比如: 按照 ke ...

  2. 【Spark篇】---Spark中Transformations转换算子

    一.前述 Spark中默认有两大类算子,Transformation(转换算子),懒执行.action算子,立即执行,有一个action算子 ,就有一个job. 通俗些来说由RDD变成RDD就是Tra ...

  3. Spark之 RDD转换成DataFrame的Scala实现

    依赖 <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2. ...

  4. Spark-Core RDD转换算子-双Value型交互

    1.union(otherDataSet) 作用:求并集. 对源 RDD 和参数 RDD 求并集后返回一个新的 RDD scala> val rdd1 = sc.parallelize(1 to ...

  5. Spark中RDD转换成DataFrame的两种方式(分别用Java和Scala实现)

    一:准备数据源     在项目下新建一个student.txt文件,里面的内容为: ,zhangsan, ,lisi, ,wanger, ,fangliu, 二:实现 Java版: 1.首先新建一个s ...

  6. Spark Core知识点复习-1

    Day1111 Spark任务调度 Spark几个重要组件 Spark Core RDD的概念和特性 生成RDD的两种类型 RDD算子的两种类型 算子练习 分区 RDD的依赖关系 DAG:有向无环图 ...

  7. Spark 3.x Spark Core详解 & 性能优化

    Spark Core 1. 概述 Spark 是一种基于内存的快速.通用.可扩展的大数据分析计算引擎 1.1 Hadoop vs Spark 上面流程对应Hadoop的处理流程,下面对应着Spark的 ...

  8. 大数据技术之_27_电商平台数据分析项目_02_预备知识 + Scala + Spark Core + Spark SQL + Spark Streaming + Java 对象池

    第0章 预备知识0.1 Scala0.1.1 Scala 操作符0.1.2 拉链操作0.2 Spark Core0.2.1 Spark RDD 持久化0.2.2 Spark 共享变量0.3 Spark ...

  9. 【Spark】RDD操作具体解释2——值型Transformation算子

    处理数据类型为Value型的Transformation算子能够依据RDD变换算子的输入分区与输出分区关系分为下面几种类型: 1)输入分区与输出分区一对一型 2)输入分区与输出分区多对一型 3)输入分 ...

随机推荐

  1. linux shell 命令笔记

    标准输入.标准输出.标准错误 File descriptors are integers associated with an opened file or data stream. File des ...

  2. .NET界面控件DevExpress v19.1.3重磅来袭

    DevExpress Universal Subscription(又名DevExpress宇宙版或DXperience Universal Suite)是全球使用广泛的.NET用户界面控件套包,De ...

  3. 双层for循环用java中的stream流来实现

    //双重for循环for (int i = 0; i < fusRecomConfigDOList.size(); i++) { for (int j = 0; j < fusRecomC ...

  4. 【BZOJ2870】最长道路

    权限题 题意 给出一棵树,点有点权,找到树上的一条路径使得路径上点的个数和其中点权最小的点的点权之积最大,输出最大值. Sol 边分治板子题啦. 边分治后对于分出来的两棵子树 , 按到左右根的最小点权 ...

  5. IIS部署复盘(杂记)

    首先,230是网站服务器,231主要放到是数据库:所以在230(部署的服务器)上部署不需要部署IIS和Oracle数据库, 231呢?231是数据库服务器:百度一下数据库服务器是什么? 文档第五步: ...

  6. input el-input 只能输入正整数验证

    字母e在js中属于数字,所以一般的正则匹配 \d 是拦不住字母e 的 正确写法为: onKeypress="return (/[\d]/.test(String.fromCharCode(e ...

  7. TCP UDP 包的最大字节

    UDP 1500,常见会设置为1024 如: ]; TCP 60*1024 UDP如果设置为1024,但是实际发送超出1024,会直接接不到应答,所以,如果你的其他命令都能正常接收,而这个命令莫名其妙 ...

  8. 笔记本连接树莓派3b(不需要屏幕)

    一.网线直连 工具:笔记本,网线,树莓派 软件:putty 过程: 将系统烧录进SD卡后,在root里添加一个名字为“ssh”的空白文件(不需后缀名)来开启ssh服务,SD卡里的cmdline.txt ...

  9. [CSP-S模拟测试]:礼物(数学)

    题目传送门(内部题80) 输入格式 第一行输入一个正整数$n$. 第二行到第$n+1$行每行两个正整数$a_i$和$b_i$表示第$i$个礼物中包含$a_i$个红宝石和$b_i$个绿宝石. 输出格式 ...

  10. [CSP-S模拟测试]:串串香(KMP)

    题目传送门(内部题75) 输入格式 输入文件$ccx.in$ 每个输入文件包含多组测试数据.输入文件的第一行为一个整数$T$,表示数据组数.接下来$T$行,每行表示一组测试数据 每行一开始,两个空格隔 ...