数值类型转换算子
1.map算子
- 定义: map(fun)函数
- 解释: 将RDD的每一个元素通过fun函数计算得到一个新的结果,新的结果我们会组合成为一个新的RDD
- 特别注意:一对一场景下,RDD的每一条数据对应新的RDD的中一条数据
- 案例:
def mapOper(sc: SparkContext): Unit = {
println("----------------map1开始------------------")
val rdd = sc.makeRDD(Array(1, 2, 3, 4, 5, 0), 1)
val map = rdd.map(_ * 3)
map.foreach(println(_)) // 结果: 3 6 9 12 15 0
println("----------------map1结束------------------")
println("----------------map2开始------------------")
val rdd2 = sc.makeRDD(Array("hbase", "flink", "kafka"))
val word = rdd2.map((_, 1))
word.foreach(println(_)) // 结果: (hbase,1) (flink,1) (kafka,1)
println("----------------map2结束------------------")
}
2.filter过滤算子
- 定义: filter(fun)算子
- 解释:将RDD中每一个元素通过fun函数计算得到一个boolean类型的返回值,如果返回值为true保留数据
- 特别注意:如果返回值为false,那么数据就舍弃 得到的新的RDD的类型和旧的RDD类型一样的
- 案例:
def filterOper(sc: SparkContext): Unit = {
println("----------------filter开始------------------")
/**
* 1 to 100 是scala中Seq集合的一种创建语法
*/
val rdd = sc.makeRDD(1 to 10)
val filter = rdd.filter((num: Int) => {
if (num % 2 == 0) {
true
} else {
false
}
})
filter.foreach(println(_)) // 结果: 2 6 4 8 10
println("----------------filter结束------------------")
}
3.flatMap压扁算子
- 定义:flatMap(fun)算子
- 解释:原先的RDD一条数据经过flatMap算子操作返回一个集合数据,集合数据中每一条数据就是新的RDD中的数据
- 特别注意:一对多
- 案例:
def flatMap(sc: SparkContext): Unit = {
println("----------------flatMap开始------------------")
val rdd = sc.makeRDD(Array("i am people", "dog is an animal"))
val flatmap = rdd.flatMap((str: String) => {
val word: Array[String] = str.split(" ")
word
})
flatmap.foreach(println(_)) // 结果: i am people dog is an animal
println("----------------flatMap结束------------------")
}
区别 | |
---|---|
map | 输入一条数据,就输出一条数据 |
flatMap | 输入一条数据,按一定的规则输出多条数据 |
4.mapPartitions
- 定义:mapPartitions(fun)算子
- 解释:和map算子函数含义一致,都是一个分区数据经过fun函数得到一个新的分区数据结果,新的结果组成新的RDD
- 案例:
def mapPartitionsOper(sc: SparkContext): Unit = {
println("----------------mapPartitions开始------------------")
val rdd: RDD[Int] = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8), 5)
val mapPartitions = rdd.mapPartitions((list: Iterator[Int]) => {
val listBuffer: ListBuffer[Int] = ListBuffer()
for (num <- list) {
println(s"处理的分区数据是 $num")
listBuffer.append(num * 3)
}
listBuffer.iterator
})
/*
处理的分区数据是 1
处理的分区数据是 2
3
处理的分区数据是 3
6
9
处理的分区数据是 4
12
处理的分区数据是 5
处理的分区数据是 6
15
18
处理的分区数据是 7
处理的分区数据是 8
21
24
*/
mapPartitions.foreach(println(_))
println("----------------mapPartitions结束------------------")
}
区别 | |
---|---|
map | 每条数据都操作一次 |
mapPartitions | 对每一分区数据操作一次 |
5.mapPartitionsWithIndex
- 定义:mapPartitionsWithIndex(fun)算子
- 解释:一次处理一个分区的数据,最后返回一个迭代器,附带传入一个分区索引
fun函数输入参数类型是一个2元组(Int,Iterator[T])=>Iterator[U] :RDD[U] - 案例:
def mapPartitionsWithIndexOper(sc: SparkContext): Unit = {
println("----------------mapPartitionsWithIndex开始------------------")
val rdd: RDD[Int] = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8), 5)
val mapPartitionsWithIndex: RDD[Int] = rdd.mapPartitionsWithIndex((index: Int, iterator: Iterator[Int]) => {
val listBuffer: ListBuffer[Int] = ListBuffer()
for (num <- iterator) {
println(s"分区为 $index , 分区的数据为 $num ")
listBuffer.append(num)
}
listBuffer.iterator
})
/*
分区为 1 , 分区的数据为 2
分区为 0 , 分区的数据为 1
分区为 1 , 分区的数据为 3
1
2
3
分区为 2 , 分区的数据为 4
4
分区为 3 , 分区的数据为 5
分区为 3 , 分区的数据为 6
5
6
分区为 4 , 分区的数据为 7
分区为 4 , 分区的数据为 8
7
8
*/
mapPartitionsWithIndex.foreach(println((_)))
println("----------------mapPartitionsWithIndex结束------------------")
}
总结
如果要实现将一个RDD数据集中每一条数据转换成为一个新的RDD数据集中记录,
可以使用map、mapPartitions、mapPartitiosWithIndex三种方式实现
一般我们建议使用mapPartitions、mapPartitiosWithIndex 这样的效率比较高点
6.sample
- 定义:sample(withReplacement, fraction, seed):RDD[T] 抽样算子
withReplacement:Boolean 是否放回抽样 true放回抽样,false代表不放回抽象
fraction:Double 如果是放回抽样 整数代表同一个数据期望被抽中几次 如果是不放回抽样,0-1之间的小数,代表的抽取比例
seed 种子 不用写(默认值) 抽样底层有算法, - 解释:抽样一部分数据进行处理分析(每个分区都会抽取数据)
- 案例:
def sampleOper(sc: SparkContext): Unit = {
println("----------------sample开始------------------")
val rdd: RDD[Int] = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3), 4)
val sample = rdd.sample(false, 0.5)
val mapPartitionsWithIndex: RDD[Int] = sample.mapPartitionsWithIndex((index: Int, data: Iterator[Int]) => {
println(s"分区为 $index , 数据为 ${data.mkString("=")}")
data
})
// 下面用来出发懒加载的算子
mapPartitionsWithIndex.count()
/*
运算结果:
分区为 0 , 数据为 1=2
分区为 1 , 数据为 5
分区为 2 , 数据为 7=8=9
分区为 3 , 数据为 1=2=3
*/
/*
val rdd: RDD[Int] = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3), 4)
val sample = rdd.sample(true, 3)
运算结果:
分区为 1 , 数据为 4=4=4=4=5=5=5=6
分区为 0 , 数据为 1=1=1=1=1=1=2=2=2=3=3=3=3=3
分区为 2 , 数据为 7=7=7=7=8=8=9=9=9=9=9
分区为 3 , 数据为 0=0=0=0=1=1=2=3=3=3=3=3=3=3
*/
println("----------------sample结束------------------")
}
7.union(另外一个RDD)
- 定义:两个RDD求一个并集返回一个新的RDD 两个RDD的类型必须保持一致
- 分区:两个RDD的分区数之和
- 案例:
def unionOper(sc: SparkContext): Unit = {
println("----------------union开始------------------")
val rdd = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8, 9), 3)
val rdd1 = sc.makeRDD(Array(1, 12, 13, 14), 2)
val rdd2 = rdd.union(rdd1)
println("union后的分区数:" + rdd2.getNumPartitions) // union后的分区数:5
rdd2.foreach((num: Int)=>print(num + ",")) // 4,1,5,2,6,3,7,8,9,1,12,13,14,
println("----------------union结束------------------")
}
8. intersection(另外一个RDD) 交集 两个RDD类型一致
- 分区:两个RDD的分区数中的最大值
- 案例:
def intersectionOper(sc: SparkContext): Unit = {
println("----------------intersection开始------------------")
val rdd = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8, 9), 3)
val rdd1 = sc.makeRDD(Array(1, 12, 13, 14), 2)
val rdd2 = rdd.intersection(rdd1)
println("intersection交集后的分区数:" + rdd2.getNumPartitions) // 交集后的分区数:3
rdd2.foreach((num: Int)=>print(num + ",")) // 1,
println("----------------intersection结束------------------")
}
9.distinct(numPartitions=默认值) 对rdd进行去重
- 分区:分区数不变
- 案例:
def distinctOper(sc: SparkContext): Unit = {
println("----------------distinct开始------------------")
val rdd = sc.makeRDD(Array(1, 1, 1, 1, 5, 6, 7, 8, 9), 3)
val rdd2 = rdd.distinct()
println("去重后的分区数:" + rdd2.getNumPartitions) // 去重后的分区数:3
rdd2.foreach(println(_)) // 1 5 6 7 8 9
println("----------------distinct结束------------------")
}
10.repartition(numPartitios) 对RDD数据集指定的分区数重新分区
- 案例:
def repartitionOper(sc: SparkContext): Unit = {
println("----------------repartition开始------------------")
val rdd = sc.makeRDD(Array(1, 1, 1, 1, 5, 6, 7, 8, 9), 10)
println(rdd.getNumPartitions) // 10
val rdd2 = rdd.repartition(2)
println(rdd2.getNumPartitions) // 2
println("----------------repartition结束------------------")
}
本文来自博客园,作者:jsqup,转载请注明原文链接:https://www.cnblogs.com/jsqup/p/16616367.html