rdd是(resilient distribute dataset)弹性分布式数据集
代表一个不可变,可分区,里面的元素可并行计算的集合
对rdd的改动,只能通过转换算子,转换成一个新的形态的rdd,所以调用转换算子返回一个新的rdd
spark的算子分为行动算子和转换算子
调用转换算子是逻辑上的传递,并没有真正运算,实际数据并没有变化,调用行动算子后,才会发给执行器,才会实际在在执行器中执行运算。
编译环境:IDEA
val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("Demo1")
val sc = new SparkContext(sparkConf)
val rdd: RDD[Int] = sc.makeRDD(1 to 10, 3)
val rdd: RDD[Int] = sc.parallelize(1 to 10, 3)
1.map算子
从A类型到B类型的映射,一般用来RDD格式转换,rdd中的元素整体上分为value类型和key-value类型
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"))
val mapRDD: RDD[(String, Int)] = rdd.map((_, 1))
mapRDD.foreach(println)
result
(李四,1)
(张三,1)
(张三,1)
(李四,1)
(王五,1)
(张三,1)
2.mapPartitions是按分区数对每个分区的进行处理的,如果有M个分区,那么每次处理一个分区,处理M次,map是按数据条数处理的,有n条数据,每次就处理N条数据,map处理n次,内存足够大时,mapPartitions比map效率高
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val mapPRdd: RDD[(String, Int)] = rdd.mapPartitions(iter => iter.map((_, 1)))
mapPRdd.foreach(println)
result
(王五,1)
(李四,1)
(张三,1)
(张三,1)
(张三,1)
(李四,1)
3,mapPartitionsWithIndex
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val mapPI: RDD[(Int, (String, Int))] = rdd.mapPartitionsWithIndex((i, iter) => {
iter.map((_, 1)).map((i, _))
})
result
(2,(李四,1))
(0,(张三,1))
(1,(王五,1))
(0,(李四,1))
(2,(张三,1))
(1,(张三,1))
4.glom算子
将每一个分区的数据,装载到一个array中
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val glomRdd: RDD[Array[String]] = rdd.glom()
var index=0
for (arr <- glomRdd.collect()) {
index+=1
println("第"+index+"分区的元素有:")
for (elem <- arr) {
println(elem)
}
}
result
第1分区的元素有:
张三
李四
第2分区的元素有:
王五
张三
第3分区的元素有:
李四
张三
groupBy算子
按传入函数的返回值分组,将key值相同的一组放在一个迭代器里
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.groupBy(x=>x).collect().foreach(println)
result
(李四,CompactBuffer(李四, 李四))
(王五,CompactBuffer(王五))
(张三,CompactBuffer(张三, 张三, 张三))
filter算子
过滤出满足条件的数据,返回一个新的RDD
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.filter(x=>x.contains("三")).foreach(println)
result
张三
张三
张三
sample算子
指定随机种子随机抽样,期望为fraction,withReplace设定抽样后是否放回,seed用于指定随机数种子
val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("Demo1")
val sc = new SparkContext(sparkConf)
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.sample(fraction = 1,withReplacement = true,seed = 10L).foreach(println)
result
李四
李四
王五
张三
张三
张三
distinct
去重
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.distinct().foreach(println)
result
李四
张三
王五
union算子求并集
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val disRdd: RDD[String] = rdd.distinct()
rdd.union(disRdd).foreach(println)
result
王五
李四
张三
张三
张三
李四
张三
李四
王五
subtract算子
去掉相同的数据,不同的保留到新rdd返回
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val disRdd: RDD[String] = rdd.distinct()
rdd.subtract(disRdd).foreach(println)
result
空
intersection算子
求交集
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val disRdd: RDD[String] = rdd.distinct()
rdd.intersection(disRdd).foreach(println)
result
张三
李四
王五
cartesian
笛卡尔积
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val disRdd: RDD[String] = rdd.distinct()
rdd.cartesian(disRdd).foreach(println)
result
(王五,李四)
(李四,李四)
(王五,张三)
(张三,张三)
(张三,李四)
(李四,张三)
(张三,王五)
(李四,王五)
(王五,王五)
(李四,李四)
(张三,张三)
(李四,王五)
(李四,张三)
(张三,李四)
(张三,王五)
(张三,张三)
(张三,李四)
(张三,王五)
zip算子
合并两个数据集为k,v形式,要求两个数据集的分区数和数据总数相同
val rdd1: RDD[Int] = sc.makeRDD(1 to 10, 2)
val rdd2: RDD[Int] = sc.makeRDD(11 to 20,2)
rdd1.zip(rdd2).collect().foreach(println)
reslut
(1,11)
(2,12)
(3,13)
(4,14)
(5,15)
(6,16)
(7,17)
(8,18)
(9,19)
(10,20)
coalesce
缩小分区,通常用于大数据集过滤后,提高小数据集的执行效率
第二个可以选择是否shuffle,使用可以让合并分区的数据均匀,不使用则能避免数据倾斜,提高执行效率
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val coalRdd: RDD[String] = rdd.coalesce(2, false)
coalRdd.saveAsTextFile("1")
result
0000
张三
李四
0001
王五
张三
李四
张三
repartiton
根据分区数,重新通过打乱重组所有的数据
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.repartition(4).saveAsTextFile("2")
reduceByKey算子
根据key进行分组,对相同key的value值传入函数进行累积计算,比如累加累乘
sortBy算子
根据传入函数的返回结果进行排序
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.map((_,1)).reduceByKey(_+_).sortBy(x=>x._2,false).collect().foreach(println)
result
(张三,3)
(李四,2)
(王五,1)
groupByKey算子
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.map((_,1)).groupByKey().collect().foreach(println)
result
(李四,CompactBuffer(1, 1))
(王五,CompactBuffer(1))
(张三,CompactBuffer(1, 1, 1))
aggregateByKey算子
第一参数为初始值,第二个为分区内操作,第二个为分区间操作
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.map((_, 1)).aggregateByKey(0)(_ + _, _ + _).collect().foreach(println)
result
(李四,2)
(王五,1)
(张三,3)
foldByKey算子
相当于分区内和分区间操作相同的aggregateByKey算子,上面代码和下面代码效果一样
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.map((_, 1)).foldByKey(0)(_+_).collect().foreach(println)
combinByKey算子
mapValues算子
争对value值进行操作
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
rdd.map((_,1)).mapValues(k=>k+1).collect().foreach(println)
PartitionBy
按照分区器进行分区,分区器有三种HashPartitioner(按key的hashcode值对分区数取余分),RangePartitioner (范围分区器),自定义分区器
自定义分区器,写一个类继承自Partitioner
val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val pRDD: RDD[(String, Int)] = rdd.map((_, 1)).partitionBy(new HashPartitioner(2))
val rdd: RDD[(Int, Int)] = sc.parallelize(List((1, 1), (5, 10), (5, 9), (2, 4), (3, 5), (3, 6), (4, 7), (4, 8), (2, 3), (1, 2)))
rdd.partitionBy(new RangePartitioner(3,rdd)).collect().foreach(println)
result
(1,1)
(2,4)
(2,3)
(1,2)
(3,5)
(3,6)
(4,7)
(4,8)
(5,10)
(5,9)
自定义分区器
val rdd: RDD[(Int, Int)] = sc.parallelize(List((1, 1), (5, 10), (5, 9), (2, 4), (3, 5), (3, 6), (4, 7), (4, 8), (2, 3), (1, 2)))
rdd.partitionBy(new MyPartitioner(3)).saveAsTextFile("3")
class MyPartitioner(num:Int) extends Partitioner{
override def numPartitions: Int = num
override def getPartition(key: Any): Int = {
if(key.toString.toInt>4){
2
}else if(key.toString.toInt>1){
1
}else{
0
}
}
}