Spark RDD常用算子

一、RDD是什么

RDD(Resilient Distributed Dataset):弹性分布式数据集。

二、RDD创建
2.1 parallelize

val rdd: RDD[Int] = sc.parallelize(List(1, 2, 3, 4, 5))

rdd.collect().foreach(println)

// 输出:1 2 3 4 5

2.2 makeRDD

val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4, 5))
rdd.collect().foreach(println)

// 输出:1 2 3 4 5

三、RDD转换算子 
3.1 Value类型
3.1.1 map

val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4, 5))
val mapRDD: RDD[Int] = rdd.map(_ * 10)
mapRDD.collect().foreach(println)

// 输出:10 20 30 40 50

3.1.2 mapPartitions

val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4, 5), 2)
val MapPartitionsRDD: RDD[Int] = rdd.mapPartitions(
iter => {
iter.map(_ * 10)
}
)
MapPartitionsRDD.collect().foreach(println)

// 输出:10 20 30 40 50

3.1.3 mapPartitionsWithIndex

val rdd = sc.makeRDD(List(1,2,3,4), 2)
val mapRDD = rdd.mapPartitionsWithIndex(
(index, iter) => {
if(index == 1) {
iter
} else {
Nil.iterator
}
}
)
mapRDD.collect().foreach(println)

// 输出:3 4

3.1.4 flatMap

val rdd: RDD[String] = sc.makeRDD(List(
"Hello Scala", "Hello Spark"
))
val flatRDD: RDD[String] = rdd.flatMap(
s => {
s.split(" ")
}
)
flatRDD.collect().foreach(println)

// 输出:Hello Scala Hello Spark

3.1.5 glom

将同一个分区的数据直接转换为相同类型的内存数组进行处理,分区不变。

val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4), 2)
val glomRDD: RDD[Array[Int]] = rdd.glom()
val maxRDD: RDD[Int] = glomRDD.map(
array => {
array.max
}
)
println(maxRDD.collect().sum)

// 输出:6

3.1.6 groupBy

将数据根据指定的规则进行分组, 分区默认不变,但是数据会被打乱重新组合,我们将这样 的操作称之为 shuffle。极限情况下,数据可能被分在同一个分区中。

val rdd = sc.makeRDD(List("Hello", "Spark", "Scala", "Hadoop"), 2)
val groupRDD = rdd.groupBy(_.charAt(0))
groupRDD.collect().foreach(println)

// 输出:(H,CompactBuffer(Hello, Hadoop)) (S,CompactBuffer(Spark, Scala))

3.1.7 filter

将数据根据指定的规则进行筛选过滤,符合规则的数据保留,不符合规则的数据丢弃。 当数据进行筛选过滤后,分区不变,但是分区内的数据可能不均衡,生产环境下,可能会出现数据倾斜。

val rdd = sc.makeRDD(List(1,2,3,4))
val filterRDD: RDD[Int] = rdd.filter(num => num % 2 != 0)
filterRDD.collect().foreach(println)

// 输出:1 3

3.1.8 sample

数据采样。有三个可选参数:设置是否放回 (withReplacement)、采样的百分比 (fraction)、随机数生成器的种子 (seed) 。

3.1.9 distinct

将数据集中重复的数据去重。

val rdd1 = sc.makeRDD(List(1,2,3,4,1,2,3,4))
val rdd2: RDD[Int] = rdd1.distinct()
rdd2.collect().foreach(println)

// 输出:1 2 3 4

3.1.10 coalesce

根据数据量缩减分区,用于大数据集过滤后,提高小数据集的执行效率。当spark程序中,存在过多的小任务的时候,可以通过coalesce方法,收缩合并分区,减少分区的个数,减小任务调度成本。

val rdd = sc.makeRDD(List(1,2,3,4))
val newRDD: RDD[Int] = rdd.coalesce(2)

3.1.11 repartition

该操作内部其实执行的是coalesce操作,参数shuffle的默认值为true。无论是将分区数多的RDD转换为分区数少的RDD,还是将分区数少的RDD转换为分区数多的RDD,repartition操作都可以完成,因为无论如何都会经shuffle过程。

val rdd = sc.makeRDD(List(1,2,3,4),2)
val newRDD: RDD[Int] = rdd.coalesce(3)

3.1.12 sortBy

排序。

val rdd = sc.makeRDD(List(5,2,3,4,1,6,7), 2)
val newRDD: RDD[Int] = rdd.sortBy(num => num)
newRDD.collect().foreach(println)

// 输出:1 2 3 4 5 6 7

3.2 双Value类型
3.2.1 intersection

求交集。

val rdd1 = sc.makeRDD(List(1,2,3,4))
val rdd2 = sc.makeRDD(List(3,4,5,6))
val rdd3: RDD[Int] = rdd1.intersection(rdd2)
println(rdd3.collect().mkString(","))

// 输出:3,4

3.2.2 union

求并集。

val rdd1 = sc.makeRDD(List(1,2,3,4))
val rdd2 = sc.makeRDD(List(3,4,5,6))

val rdd4: RDD[Int] = rdd1.union(rdd2)
println(rdd4.collect().mkString(","))

// 输出:1,2,3,4,3,4,5,6

3.2.3 subtract

求差集。

val rdd1 = sc.makeRDD(List(1,2,3,4))
val rdd2 = sc.makeRDD(List(3,4,5,6))

val rdd5: RDD[Int] = rdd1.subtract(rdd2)
println(rdd5.collect().mkString(","))

// 输出:1,2

3.2.4 zip

拉链。

val rdd1 = sc.makeRDD(List(1,2,3,4))
val rdd2 = sc.makeRDD(List(3,4,5,6))

val rdd6: RDD[(Int, Int)] = rdd1.zip(rdd2)
println(rdd6.collect().mkString(","))

// 输出:(1,3),(2,4),(3,5),(4,6)

3.3 Key-Value类型
3.3.1 partitionBy

将数据按照指定 Partitioner 重新进行分区。Spark 默认的分区器是 HashPartitioner。

3.3.2 reduceByKey

可以将数据按照相同的 Key 对 Value 进行聚合。

val rdd = sc.makeRDD(List(
("a", 1), ("a", 2), ("a", 3), ("b", 1), ("b", 2)
))
val reduceRDD: RDD[(String, Int)] = rdd.reduceByKey((x: Int, y: Int) => {
x + y
})
reduceRDD.collect().foreach(println)

// 输出:(a,6) (b,3)

3.3.3 groupByKey

将数据源的数据根据 key 对 value 进行分组

val rdd = sc.makeRDD(List(
("a", 1), ("a", 2), ("a", 3), ("b", 1), ("b", 2)
))
val groupRDD: RDD[(String, Iterable[Int])] = rdd.groupByKey()
groupRDD.collect().foreach(println)

// 输出:(a,CompactBuffer(1, 2, 3)) (b,CompactBuffer(1, 2))

3.3.4 aggregateByKey

将数据根据不同的规则进行分区内计算和分区间计算

val rdd = sc.makeRDD(List(
("a", 1), ("a", 2), ("a", 3), ("a", 4)
), 2)
rdd.aggregateByKey(0)(
(x, y) => math.max(x ,y),
(x ,y) => x + y
).collect().foreach(println)

// 输出:(a,6)

3.3.5 foldByKey

当分区内计算规则和分区间计算规则相同时,aggregateByKey就可以简化为foldByKey。

3.3.6 combineByKey

最通用的对 key-value 型 rdd 进行聚集操作的聚集函数(aggregation function)。类似于 aggregate(),combineByKey()允许用户返回值的类型与输入不一致。

3.3.7 sortByKey

在一个(K,V)的RDD上调用,K必须实现Ordered接口(特质),返回一个按照key进行排序的。

3.3.8 join

在类型为(K,V)和(K,W)的RDD上调用,返回一个相同 key 对应的所有元素连接在一起的 (K,(V,W))的 RDD。笛卡儿积。

val rdd1 = sc.makeRDD(List(
("a", 1), ("b" ,2), ("c", 3)
))
val rdd2 = sc.makeRDD(List(
("a", 4), ("b", 5), ("c", 6)
))
val joinRDD: RDD[(String, (Int, Int))] = rdd1.join(rdd2)

joinRDD.collect().foreach(println)

// 输出:(a,(1,4)) (b,(2,5)) (c,(3,6))

3.3.9 leftOuterJoin

类似于SQL语句的左外连接。

val rdd1 = sc.makeRDD(List(
("a", 1), ("b" ,2), ("c", 3)
))
val rdd2 = sc.makeRDD(List(
("a", 4), ("b", 5)
))
val leftJoinRDD: RDD[(String, (Int, Option[Int]))] = rdd1.leftOuterJoin(rdd2)
leftJoinRDD.collect().foreach(println)

// 输出:(a,(1,Some(4))) (b,(2,Some(5))) (c,(3,None))

3.3.10 cogroup

在类型为(K,V)和(K,W)的 RDD 上调用,返回一个(K,(Iterable,Iterable))类型的RDD。

val rdd1 = sc.makeRDD(List(
("a", 1), ("b" ,2), ("c", 3)
))
val rdd2 = sc.makeRDD(List(
("a", 4), ("b", 5), ("c", 6), ("c", 8)
))
val cgRDD: RDD[(String, (Iterable[Int], Iterable[Int]))] = rdd1.cogroup(rdd2)
cgRDD.collect().foreach(println)

// 输出:(a,(CompactBuffer(1),CompactBuffer(4)))

              (b,(CompactBuffer(2),CompactBuffer(5)))
              (c,(CompactBuffer(3),CompactBuffer(6, 8)))

四、RDD行动算子
4.1 reduce

聚集 RDD 中的所有元素,先聚合分区内数据,再聚合分区间数据。

val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
println(rdd.reduce(_ + _))

// 输出:10

4.2 collect

在驱动程序中,以数组 Array 的形式返回数据集的所有元素。

val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
rdd.collect().foreach(println)

// 输出:1 2 3 4

4.3 count

返回 RDD 中元素的个数。

val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
println(rdd.count())

// 输出:4

4.4 first

返回 RDD 中的第一个元素。

val rdd: RDD[Int] = sc.makeRDD(List(4, 2, 3, 1))
println(rdd.first())

// 输出:4

4.5 take

返回一个由 RDD 的前 n 个元素组成的数组。

val rdd: RDD[Int] = sc.makeRDD(List(4, 2, 3, 1))
rdd.take(2).foreach(println)

// 输出:4 2

4.6 takeOrdered

返回该 RDD 排序后的前 n 个元素组成的数组。

val rdd: RDD[Int] = sc.makeRDD(List(4, 2, 3, 1))
rdd.takeOrdered(2).foreach(println)

// 输出:1 2

4.7 aggregate

分区的数据通过初始值和分区内的数据进行聚合,然后再和初始值进行分区间的数据聚合。

val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),4)
println(rdd.aggregate(10)(_ + _, _ + _))

// 输出:60

4.8 fold

折叠操作,aggregate 的简化版操作。

val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),4)
println(rdd.fold(0)(_+_))

// 输出:10

4.9 countByKey

计算每个键出现的次数。

4.10 saveAsTextFile

保存成Text 文件。

4.11 saveAsObjectFile

序列化成对象保存到文件。

4.12 saveAsSequenceFile

保存成Sequencefile文件。

4.13 foreach

分布式遍历RDD中的每一个元素,调用指定函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值