Spark从零开始学 三

了解下Spark的函数API


一 . 创建RDD

1.普通数组创建RDD

val a = sc.parallelize(1to9,3)

这个含义是,生成 1 到 9 的9个数字,分成 3 个区来存储


2.普通文本文件创建RDD

val b = sc.textFile("README.md")

这个是读取文本文件来存储到RDD中,一行作为一条记录


二 函数

map

map是对RDD中的每个元素都执行一个指定的函数来产生一个新的RDD。 任何原RDD中的元素在新RDD中都有且只有一个元素与之对应。

val rdd = sc.parallelize(1 to 9, 3)
val rdd2 = rdd.map(x => x * 2)
rdd2.foreach(x => print(x + " "))

结果:

2 4 6

8 10 12

14 16 18

上一个map方法表示把原RDD的每一个元素乘以 2 得到新的RDD


mapValues

作用于有KV的RDD,基于原有的RDD,K 不变,V 做对应的计算,得到新的包含原有K和新V的RDD,和map一样是对每个元素都要执行,也是一对一

val rdd = sc.parallelize(List("DOG", "TIGER", "LION", "CAT"), 2)

val rdd2 = rdd.map(a => (a.length, a)).mapValues("x" + _ + "x")

rdd2.foreach(x => print(x + " "))

这里初始化一个RDD,2 个分区,第一个map函数得到KV格式的RDD,如(3,DOG),mapValues函数对V计算,那么新的V就是xDOGx

结果:

(3,xDOGx) (5,xTIGERx)

(4,xLIONx) (3,xCATx)


flatMap

与map类似,也是处理原RDD中的所有元素,生成一个新RDD

区别是原RDD中的一个元素经map处理后只能生成一个元素,而原RDD中的元素经flatMap处理后可生成多个元素来构建新RDD。

举例:对原RDD中的每个元素x产生y个元素(从x到5,全部的元素)

val rdd = sc.parallelize(1 to 5, 2)

val rdd2 = rdd.flatMap(x => x to 5)

rdd2.foreach(x => print(x + " "))

初始化一个RDD,存有1 2 3 4 5 ,五个元素2个区,flatMap函数表示将每个元素扩展开,该元素到5的所有元素

举个例子,如果x=2,那么经过flatMap处理过后返回 2 3 4 5

结果:

1 2 3 4 5 2 3 4 5

3 4 5 4 5 5


flatMapValues

与mapValues相似,每个一元素的V被输入函数映射为一系列的值,然后这些值再与原RDD中的K组成一系列新的KV对。

val rdd = sc.parallelize(List((1, 2), (3, 4), (3, 6)))

val rdd2 = rdd.flatMapValues(x => x.to(5))

rdd2.foreach(x => print(x + " "))

初始化一个原RDD,这里采用默认的一个分区

这里举个例子,原RDD要处理KV元素(1,2),经过flatMapValues把V扩展开为 2 3 4 5,再与原K组成新的KV对 (1,2) (1,3) (1,4) (1,5)

结果:

(1,2) (1,3) (1,4) (1,5) (3,4) (3,5)


reduce

reduce将RDD中元素两两传递给输入函数,同时产生一个新的值,新产生的值与RDD中下一个元素(第三个元素)再被传递给输入函数直到最后只有一个值为止。

val rdd = sc.parallelize(1 to 10)

val rdd2 = rdd.reduce((x, y) => x + y)

println(rdd2)

具体过程,RDD有1 2 3 4 5 6 7 8 9 10个元素, 这里 reduce((x,y)=>x+y) 等同为 reduce(_ + _)

1+2=3  3+3=6  6+4=10  10+5=15  15+6=21  21+7=28  28+8=36  36+9=45  45+10=55

结果:

55


reduceByKey

顾名思义,reduceByKey就是对元素为KV对的RDD中K相同的元素的V进行reduce

因此,K相同的多个元素的值V被reduce为一个值,然后与原RDD中的K组成一个新的KV对。

val rdd = sc.parallelize(List((1, 2), (3, 4), (3, 6)))

val rdd2 = rdd.reduceByKey((x, y) => x + y)

rdd2.foreach(x => print(x + " "))

这里表示对相同K的V做求和计算,如(3,4)和(3,6),这里K相同,V求和为10,组成一个新的KV对为(3,10), 这里 reduce((x,y)=>x+y) 等同为 reduce(_ + _)

结果:

(1,2) (3,10)


union

将两个RDD中的数据集进行合并,最终返回两个RDD的并集,若RDD中存在相同的元素也不会去重

val rdd = sc.parallelize(1.to(5))

val rdd1 = sc.parallelize(2 to 4)

val rdd2 = rdd.union(rdd1)

rdd2.foreach(x => print(x + " "))

println("分区个数:" + rdd2.partitions.size)

rdd是1 2 3 4 5,rdd1是2 3 4,两个RDD都为一个默认分区

注意:虽然合并为一个数据集RDD,但是合并后的RDD有两个分区,该操作后分区数=两个RDD分区数之和

最后一行代码是查看一个RDD的分区数

结果:

1 2 3 4 5

2 3 4


intersection
这个是取两个RDD的交集
val rdd = sc.parallelize(1.to(5))
val rdd1 = sc.parallelize(2 to 7)
val rdd2 = rdd.intersection(rdd1)
rdd2.foreach(x => print(x + " "))
这里的交集,最后结果RDD的分区数不固定
结果:
2 3 4 5

distinct
去重
val rdd = sc.parallelize(List(1, 1, 2, 5, 2, 9, 6, 1))
val distinctRDD=rdd.distinct()
distinctRDD.foreach(x => print(x + " "))
结果:
1 6 9 5 2

cartesian
对两个RDD中所有元素进行笛卡尔积操作
val rdd = sc.parallelize(1.to(3))
val rdd1 = sc.parallelize(2 to 4)
val rdd2 = rdd.cartesian(rdd1)
rdd2.foreach(x => print(x + " "))
这里原来的RDD的分区,执行该操作后分区数=rdd1的分区数 * rdd2的分区数
结果:
(1,2) (1,3) (1,4) (2,2) (2,3) (2,4) (3,2) (3,3) (3,4)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章