spark算子大全glom_spark 算子总结

本文主要介绍spark中常用的算子的作用记忆部分示例总结。

从总体上来分,spark算子可以分为两大类:transformation和action,其中transformation触发会记录元数据信息,延迟执行,只有触发action才会真正的执行计算。

从小方向上来讲,spark算子可以分为三种类型:value类型transformation算子,key-value类型transformation算子以及action算子。what is RDD?

Internally, each RDD is characterized by five main properties:

接下来介绍常用的一些spark算子。

transformation算子

value类型transformation算子

map算子

map算子将原来RDD中的每一个数据通过map中的用户自定义方法f映射转变成新的元素。1

2

3

4

5

6

7

8scala> val rdd1 = sc.parallelize(List(1, 2, 3))

rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at :24

scala> val rdd2 = rdd1.map(_*10)

rdd2: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[1] at map at :26

scala> rdd2.collect()

res0: Array[Int] = Array(10, 20, 30)

flatMap算子

flatMap将RDD中的每一个元素通过函数f转成新的元素,并将RDD的每个集合中的元素合并成一个集合。1

2

3

4

5scala> val rdd1 = sc.parallelize(Array("a b c", "d e f", "h i j"))

rdd1: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[8] at parallelize at :24

scala> val rdd2 = rdd1.flatMap(_.split(' ')).collect

rdd2: Array[String] = Array(a, b, c, d, e, f, h, i, j)

mapPartitions算子

与map类似,但是在RDD的每个分区(块)上分别运行,所以当在T类型的RDD上运行时,func的类型必须是Iterator=> Iterator 。

glom 算子

glom将每个分区形成一个数组,内部实现返回ClommedRDD

union算子

使用union函数要保证两个RDD元素的数据类型相同,返回的RDD类型与被合并的RDD数据类型相同,并不进行去重操作,保存所有元素。

如果去重,可以使用distinct()进行处理。

cartesian算子

对两个RDD的所有元素进行笛卡尔积操作,返回CartesianRDD.1

2

3

4

5

6

7

8

9

10

11scala> val rdd1 = sc.parallelize(List("tom", "jerry"))

rdd1: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[21] at parallelize at :24

scala> val rdd2 = sc.parallelize(List("tom", "kitty", "shuke"))

rdd2: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[22] at parallelize at :24

scala> val rdd3 = rdd1.cartesian(rdd2)

rdd3: org.apache.spark.rdd.RDD[(String, String)] = CartesianRDD[23] at cartesian at :28

scala> rdd3.collect

res3: Array[(String, String)] = Array((tom,tom), (tom,kitty), (tom,shuke), (jerry,tom), (jerry,kitty), (jerry,shuke))

groupBy算子

将元素通过函数生成相应的key,数据转换为key-value形式,将key相同的元素分为一组。1

2

3

4

5

6

7

8scala> rdd3.collect

res1: Array[(String, (Int, Int))] = Array((tom,(1,8)), (jerry,(2,9)))

scala> val rdd4 = rdd3.groupByKey

rdd4: org.apache.spark.rdd.RDD[(String, Iterable[(Int, Int)])] = MapPartitionsRDD[20] at groupByKey at :30

scala> rdd4.collect

res2: Array[(String, Iterable[(Int, Int)])] = Array((tom,CompactBuffer((1,8))), (jerry,CompactBuffer((2,9))))

filter算子

对RDD中的元素按照函数f进行过滤。1

2

3

4

5scala> val a = sc.parallelize(1 to 9, 2)

a: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[11] at parallelize at :24

scala> val rdd = a.filter(_ <5).collect

rdd: Array[Int] = Array(1, 2, 3, 4)

distinct算子

对RDD中的元素进行去重操作。

subtract算子

对两个RDD进行集合的差操作。

sample算子

sample 将 RDD 这个集合内的元素进行采样,获取所有元素的子集。用户可以设定是否有放回的抽样、百分比、随机种子,进而决定采样方式。内部实现是生成 SampledRDD(withReplacement, fraction, seed)。

takeSample算子

类似sample算子,通过设定采样个数进行采样,返回结果的集合为单机数组。

cache算子

将RDD元素缓存到内存中

persist算子

persist 函数对 RDD 进行缓存操作。

mapValues算子

针对(key, value)类型中的value进行map操作。

combineByKey算子

按照键值key进行聚合。1

2

3

4

5

6

7

8val initialScores = Array(("Fred", 88.0), ("Fred", 95.0), ("Fred", 91.0), ("Wilma", 93.0), ("Wilma", 95.0), ("Wilma", 98.0))

val d1 = sc.parallelize(initialScores)

type MVType = (Int, Double) //定义一个元组类型(科目计数器,分数)

d1.combineByKey(

score => (1, score),

(c1: MVType, newScore) => (c1._1 + 1, c1._2 + newScore),

(c1: MVType, c2: MVType) => (c1._1 + c2._1, c1._2 + c2._2)

).map { case (name, (num, socre)) => (name, socre / num) }.collect

reduceByKey算子

combineByKey的简单版,将两个值按照key进行合并。

partitionBy算子

将RDD进行分区操作。

Cogroup算子

join算子

join算子对两个需要连接的RDD进行cogroup操作,将相同key的数据放在一个分区,之后对新的RDD的每一个key元素进行笛卡尔积操作,最后构成一个新的集合。返回值为RDD[(K, (V, W))]

1

2

3

4

5

6

7

8scala> val rdd1 = sc.parallelize(List(("tom", 1), ("jerry", 2), ("kitty", 3)))

rdd1: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[0] at parallelize at :24

scala> val rdd2 = sc.parallelize(List(("jerry", 9), ("tom", 8), ("shuke", 7)))

rdd2: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[1] at parallelize at :24

scala> val rdd3 = rdd1.join(rdd2).collect

rdd3: Array[(String, (Int, Int))] = Array((tom,(1,8)), (jerry,(2,9)))

leftOutJoin和rightOutJoin算子

LeftOutJoin(左外连接)和RightOutJoin(右外连接)相当于在join的基础上先判断一侧的RDD元素是否为空,如果为空,则填充为空。 如果不为空,则将数据进行连接运算,并返回结果。1

2

3

4

5scala> val rdd4 = rdd1.leftOuterJoin(rdd2).collect

rdd4: Array[(String, (Int, Option[Int]))] = Array((tom,(1,Some(8))), (jerry,(2,Some(9))), (kitty,(3,None)))

scala> val rdd5 = rdd1.rightOuterJoin(rdd2).collect

rdd5: Array[(String, (Option[Int], Int))] = Array((tom,(Some(1),8)), (jerry,(Some(2),9)), (shuke,(None,7)))

action类型算子

foreach算子

foreach对RDD中的每个元素都应用函数f,返回UNIT

saveAsTextFile算子

将数据输出存储在HDFS指定目录中。

saveAsObjectFile算子

将数据输出以sequencefile的格式存储在HDFS目录中。

collect算子

collect将分布式的RDD返回一个ARRAY类型数组。

collectAsMap算子

对(k, v)类型RDD数据返回一个单机hashMap,对于重复的RDD元素,后面的元素覆盖前面的元素。1

2

3

4

5scala> var rdd1 = sc.parallelize(List(("A", 1), ("B", 2), ("C", 3)))

rdd1: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[28] at parallelize at :24

scala> val rdd2 = rdd1.collectAsMap()

rdd2: scala.collection.Map[String,Int] = Map(A -> 1, C -> 3, B -> 2)

reduceByKeyLocally算子

实现的是先reduce再collectAsMap的功能,先对RDD的整体进行reduce操作,然后再收集所有结果返回为一个HashMap。

loopup算子

作用于K-V类型的RDD上,返回指定K的所有V值。1

2scala> val rdd2 = rdd1.lookup("A")

rdd2: Seq[Int] = WrappedArray(1)

count算子

返回RDD的元素个数。

top算子

返回最大的K个元素。

reduce算子

对RDD中的元素进行reduceLeft函数的操作。分别对每个分区进行聚合。1

2

3

4

5scala> val a = sc.parallelize(1 to 100, 3)

a: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at :24

scala> a.reduce(_ + _)

res0: Int = 5050

fold算子

聚合每个分区的值,每个分区内的聚合变量用zeroValue初始化。

def fold(zeroValue: T)(op: (T, T) => T): T1

2

3

4

5

6

7

8

9

10

11scala> val a = sc.parallelize(1 to 100, 3)

a: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at :24

scala> a.fold(0)(_ + _)

res2: Int = 5050

scala> a.fold(1)(_ + _)

res3: Int = 5054

scala> a.fold(2)(_ + _)

res4: Int = 5058

aggregate算子

aggregate先对每个分区的所有元素进行aggregate操作,再对分区的结果进行fold操作。

aggreagate与fold和reduce的不同之处在于,aggregate相当于采用归并的方式进行数据聚集,这种聚集是并行化的。 而在fold和reduce函数的运算过程中,每个分区中需要进行串行处理,每个分区串行计算完结果,结果再按之前的方式进行聚集,并返回最终聚集结果。1

2scala> a.aggregate(0)(_+_, _+_)

res8: Int = 5050

根据Zhen He的解释,聚合功能允许用户将两个不同的函数应用在RDD中,在每个分区中应用第一个reduce函数,将每个分区内的数据减少为单个结果。第二个reduce函数函数将用于将所有分区的结果聚合在一起,以得到最终结果。

你可能感兴趣的:(spark算子大全glom)