一:转换算子:
1.Map:
将数据进行逐条映射转换
val a = sc.makeRDD(1 to 3)
val b = a.map(x=>x*2)
b.collect --Array(2, 4, 6)
2.MapPartitions
将数据以分区为单位发送到计算节点进行处理
val a = sc.makeRDD(1 to 3)
val b = a.mapPartitions(x=>x.filter(_%2==0)).collect
-- Array(2)
val c = a.mapPartitions(x=>for(elem<-x) yield(elem,if(elem > 2) "b" else "a")).collect
--Array((1,a), (2,a), (3,b))
yield的主要作用是记住每次迭代中的有关值,并逐一存入到一个数组中
3.flatMap
def flatMap[U: ClassTag](f: T => TraversableOnce[U]): RDD[U] = withScope { val cleanF = sc.clean(f) new MapPartitionsRDD[U, T](this, (_, _, iter) => iter.flatMap(cleanF)) }
将处理的数据进行扁平化后再进行映射处理,所以算子也称之为扁平映射。可以理解成先flat,再map操作
--利用flatMap对数据进行wordCount
--hdfs中上传一个txt文件,内容为需要计算count的文本,以" "分割
sc.textFile("hdfs://192.168.10.129:9000/kb23/tmp/*.txt") \ --读取文件
.flatMap(x=>x.split(" ")). \ --以" "扁平化操作
map(x=>(x,1)). \ --逐条映射转换
reduceByKey(_+_). \ --根据key值计算
glom.collect
4.groupBy/groupByKey
(1):groupBy
def groupBy[K](f: Int => K,numPartitions: Int)(implicit kt: scala.reflect.ClassTag[K]): org.apache.spark.rdd.RDD[(K, Iterable[Int])]
val a = sc.makeRDD(1 to 10)
val b = a.groupBy(x=>x/2==0,2).collect.foreach(println)
--(false,CompactBuffer(2, 3, 4, 5, 6, 7, 8, 9, 10))
--(true,CompactBuffer(1))
(2):groupByKey
def groupByKey(numPartitions: Int): org.apache.spark.rdd.RDD[(String, Iterable[Int])]
val a = sc.makeRDD(Array(("a",1),("b",2),("a",2),("c",1)))
val c = a.groupByKey(2)
--Array(Array((b,CompactBuffer(2))), Array((a,CompactBuffer(1, 2)), (c,CompactBuffer(1))))
--两个分区
5.filter
将数据根据指定的规则进行筛选过滤,符合规则的数据保留,不符合规则的数据丢弃。 当数据进行筛选过滤后,分区不变,但是分区内的数据可能不均衡,生产环境下,可能会出现数据倾斜
val a = sc.makeRDD(Array(("zhangsan",1),("lisi",2),("zhangyouzhi",3)))
val b = a.filter(x=>x._1.startsWith("zhang")).collect
--Array((zhangsan,1), (zhangyouzhi,3))
6.sample
def sample(withReplacement: Boolean,fraction: Double,seed: Long): org.apache.spark.rdd.RDD[Int]
第一个参数指抽出的数据是否放回,true 为有放回的抽样,false 为无放回的抽样
第二个参数指每个数抽取的概率
第三个参数指指定随机数生成器种子
val a = sc.makeRDD(1 to 10)
--为true时,可能会抽取到重复数字
a.sample(true,0.3,10).collect
--Array(7, 10, 10)
--false
a.sample(false,0.3,10).collect
--Array(7, 10)
7.distinct
将数据集中重复的数据去重
def distinct(): org.apache.spark.rdd.RDD[Int]
def distinct(numPartitions: Int)(implicit ord: Ordering[Int]): org.apache.spark.rdd.RDD[Int]
val a = sc.makeRDD(Array(1,2,3,4,2,1,3))
a.distinct.collect
--Array(4, 1, 2, 3)
a.distinct(3).glom().collect --去重后分区
-- Array(Array(3), Array(4, 1), Array(2))
8.coalesce
根据数据量缩减分区,用于大数据集过滤后,提高小数据集的执行效率当 spark 程序中,存在过多的小任务的时候,可以通过 coalesce 方法,收缩合并分区,减少分区的个数,减小任务调度成本。
coalesce方法默认不会将分区的数据打乱重新组合。这种情况下的缩减分区可能会导致数据不均衡,出现数据倾斜。如果想要让数据均衡,可以进行shuffle处理。
def coalesce(numPartitions: Int,shuffle: Boolean,partitionCoalescer: Option[org.apache.spark.rdd.PartitionCoalescer])(implicit ord: Ordering[Int]): org.apache.spark.rdd.RDD[Int]
val d = sc.makeRDD(1 to 20,5)
--coalesce,shuffle为false
d.coalesce(3,false).glom.foreach(x=>println(x.toList))
--List(13, 14, 15, 16, 17, 18, 19, 20)
--List(1, 2, 3, 4)
--List(5, 6, 7, 8, 9, 10, 11, 12)
--coalesce,shuffle为true
d.coalesce(3,true).glom.foreach(x=>println(x.toList))
--List(2, 5, 8, 10, 13, 16, 17, 20)
--List(3, 6, 11, 14, 18)
--List(1, 4, 7, 9, 12, 15, 19)
9.reparitition(默认coalesce为true)
d.repartition(3).glom.foreach(x=>println(x.toList))
--List(1, 4, 7, 9, 12, 15, 19)
--List(3, 6, 11, 14, 18)
--List(2, 5, 8, 10, 13, 16, 17, 20)
10.sortBy/sortByKey
(1):sortBy
排序,默认升序
val d = sc.makeRDD(Array(2,1,4,5,2,6,8,3,4,72,3))
--升序
d.sortBy(x=>x).collect
--Array(1, 2, 2, 3, 3, 4, 4, 5, 6, 8, 72)
--降序
d.sortBy(x=> -x).collect
--Array(72, 8, 6, 5, 4, 4, 3, 3, 2, 2, 1)
(2):sortByKey
根据key值排序
def sortByKey(ascending: Boolean,numPartitions: Int): org.apache.spark.rdd.RDD[(Int, Int)]
val d = sc.makeRDD(Array((1,2),(1,3),(3,2),(4,2),(2,1)))
--true:默认排序,从小到大
d.sortByKey(true).collect
--Array((1,2), (1,3), (2,1), (3,2), (4,2))
--false:从大到小
d.sortByKey(false).collect
--Array((4,2), (3,2), (2,1), (1,2), (1,3))
11.combineByKey(高阶算子)
def combineByKey[C](
createCombiner: V => C,
mergeValue: (C, V) => C,
mergeCombiners: (C, C) => C): RDD[(K, C)]
combineByKey:方法需要三个参数
第一个参数表示:将相同key的第一个数据进行结构的转换,实现操作
第二个参数表示:分区内的计算规则
第三个参数表示:分区间的计算规则
val b = sc.parallelize(Array(("hello",1),("spark",1),("hello",2),("hive",1)),2)
b.combineByKey(x=>(x,1), (acc:(Int,Int),v)=>(acc._1+v,acc._2+1), (acc1:(Int,Int),acc2:(Int,Int))=>(acc1._1+acc2._1,acc1._2+acc2._2)).collect
二:行动算子:
1.reduce/reduceByKey
(1):reduce
对值进行聚合操作
val d = sc.makeRDD(1 to 10)
d.reduce(_+_)
--Int = 55
(2):reduceByKey
可以将数据按照相同 Key 的数据进行 Value 进行聚合操作。如果key的数据只有一个,不会参与运算
def reduceByKey(func: (Int, Int) => Int): org.apache.spark.rdd.RDD[(String, Int)]
def reduceByKey(func: (Int, Int) => Int,numPartitions: Int): org.apache.spark.rdd.RDD[(String, Int)]
def reduceByKey(partitioner: org.apache.spark.Partitioner,func: (Int, Int) => Int): org.apache.spark.rdd.RDD[(String, Int)]
val a = sc.makeRDD(Array(("a",1),("b",2),("a",2),("c",1)))
val b = a.reduceByKey((x,y)=>x+y).collect
--Array((a,3), (b,2), (c,1))