Spark学习(六)常用算子整理

本文深入解析了Spark中RDD的12种常用算子,包括MapPartition、Map、MapPartitionWithIndex等,阐述了它们的功能、使用场景及实现原理。通过实例展示了如何利用这些算子进行数据处理和优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、MapPartition

遍历的单位是每一个partition。
遍历原理:将每一个partition的数据先加载到内存,然后再一条一条遍历。

rdd.mapPartitions((elems:Iterator[Int]) => {
      println("创建连接")
    while(elems.hasNext){
      println("拼接SQL语句 " + elems.next)
    }
    println("提交")
    elems
})

2、Map

遍历单位是每一条记录。

3、MapPartitionWithIndex

在遍历每一个partition的时候能够拿到每一个分区的ID号,这个算子一般用于测试环境。

rdd.mapPartitionsWithIndex((index,iterator) =>{
   println("partitonId: " + index)
   while(iterator.hasNext){
      println(iterator.next)
   }
 }).count()

4、getNumPartitions

获取RDD的分区数

val partitionNum1 = rdd.
val partitionNum2 = rdd.partitions.length

5、coalesce

coalesce(…,true)若参数为true,说明分区的时候需要产生shuffle,若参数为false说明不需要产生shuffle。
增加RDD的分区数使用coalesce(…,true)或者repartition

val coalesceRDD1 = facePowerRDD.coalesce(6, true)   
println("coalesceRDD1.getNumPartitions:" + coalesceRDD1.getNumPartitions)
coalesceRDD1.mapPartitionsWithIndex((index,iterator)=>{
    println("partitionId" + index)
   while(iterator.hasNext){
    println(iterator.next)
   }
    iterator
}).count()

减少RDD的分区数,使用coalesce(…,false),也可以使用coalesce(…,true)但是效率会降低。

facePowerRDD
    .coalesce(2, false)
    .mapPartitionsWithIndex((index,iterator)=>{
    println("partitionId" + index)
  while(iterator.hasNext){
   println(iterator.next)
 }
   iterator
}).count()

6、union

合并,他只是将rdd1与rdd2在逻辑上进行合并,并不会真正进行数据的合并以传输。

val rdd1 = sc.parallelize(1 to 10, 3)
val rdd2 = sc.makeRDD(11 to 20,3)
val unionRDD = rdd1.union(rdd2)
println(unionRDD.getNumPartitions)

7、zip

将两个RDD进行横向合并,但是zip是对应位置合并。
比如:非KV格式的RDD1、RDD2 zip KV格式的RDD

val zipRDD = rdd1.zip(rdd2)
zipRDD.foreach(println)

注意:

  1. 要进行zip的两个RDD的元素数必须一致。
  2. 要进行zip的两个RDD的分区数必须一致。

8、zipWitIndex

给RDD中的每一个元素加上一个唯一的索引号,非KV的RDD变成了KV格式的RDD。

val zipWithIndexRDD = rdd1.zipWithIndex()
zipWithIndexRDD.foreach(println)
zipWithIndexRDD.map(_.swap).lookup(2).foreach(println)

9、zipWithUniqueId

给RDD中的每一个元素加上一个唯一的索引号,非KV的RDD变成了KV格式的RDD。
每一个分区的第一个元素的索引号就是当前分区的分区号;
每一个分区的第二个元素的索引号就是第一个元素+分区数。

rdd1
   .zipWithUniqueId()
   .mapPartitions(iterator=>{
    while(iterator.hasNext){
     println(iterator.next)
    }
    iterator
}).count()

10、take(n)

取这个RDD中前n个元素,是action类算子。

11、first

取这个RDD中第一个元素,与task(1)一样,也是action类算子。

rdd1.take(5).foreach(println)
//first = take(1)
println(rdd1.first())

12、combineByKey

rdd.combineByKey(初始化函数,combiner聚合函数,reduce大聚合函数)
combineByKey作用步骤:

  1. 分组完成后,初始化函数会作用到每组数据的第一个元素上。
  2. combiner聚合函数作用到每组数据上,得到最终的combiner小聚合结果。
  3. 将reduce大聚合函数作用在每组数据上。

总结:
val conf = new SparkConf().setMaster(“local”)

  1. local:使用1个线程来模拟。
  2. local[10]:代码在本机使用10个线程来模拟spark的执行。
  3. local[*]:电脑还剩下几个core,那么就启动多少个线程来模拟。
### 三、Spark常用算子介绍及使用场景 Apache Spark 提供了丰富的算子(Operator),用于实现数据的转换和处理。这些算子可以分为两类:**转换算子(Transformation)** 和 **行动算子(Action)**。转换算子是惰性执行的,只有遇到行动算子才会真正触发任务的执行。Spark算子数量远多于 MapReduce,具备更强的表达力和灵活性,能够满足大多数大数据处理场景的需求[^1]。 --- #### 3.1 转换算子(Transformation) 转换算子用于将一个 RDD 转换为另一个 RDD,其执行是惰性的。 ##### 3.1.1 `map` `map` 算子用于对 RDD 中的每个元素应用一个函数,并返回新的 RDD。它是一对一的映射关系。 ```scala val rdd = sc.parallelize(Seq(1, 2, 3, 4)) val mappedRdd = rdd.map(x => x * 2) ``` ##### 3.1.2 `filter` `filter` 算子用于筛选出满足条件的元素,生成新的 RDD。 ```scala val filteredRdd = rdd.filter(x => x % 2 == 0) ``` ##### 3.1.3 `flatMap` `flatMap` 与 `map` 类似,但每个输入元素可以映射为多个输出元素,最终结果是扁平化的 RDD。 ```scala val flatMappedRdd = rdd.flatMap(x => Seq(x, x * 2)) ``` ##### 3.1.4 `union` `union` 算子用于合并两个具有相同数据类型的 RDD,不进行去重操作。 ```scala val rdd1 = sc.parallelize(Seq(1, 2, 3)) val rdd2 = sc.parallelize(Seq(3, 4, 5)) val unionRdd = rdd1.union(rdd2) // 结果包含 1,2,3,3,4,5 ``` ##### 3.1.5 `distinct` `distinct` 算子用于去除 RDD 中的重复元素。 ```scala val distinctRdd = unionRdd.distinct() ``` ##### 3.1.6 `join` `join` 算子用于对两个键值对 RDD 进行连接操作,返回键相同的所有键值对组合。 ```scala val rdd1 = sc.parallelize(Seq(("a", 1), ("b", 2))) val rdd2 = sc.parallelize(Seq(("a", 3), ("b", 4))) val joinedRdd = rdd1.join(rdd2) // 结果为 ("a", (1,3)), ("b", (2,4)) ``` ##### 3.1.7 `groupByKey` `groupByKey` 算子用于将键值对 RDD 中相同键的值进行分组。 ```scala val groupedRdd = rdd1.groupByKey() ``` ##### 3.1.8 `reduceByKey` `reduceByKey` 算子用于对键值对 RDD 中相同键的值进行聚合操作。 ```scala val reducedRdd = rdd1.reduceByKey(_ + _) ``` --- #### 3.2 行动算子(Action) 行动算子用于触发 Spark 作业的执行,并返回结果给 Driver 程序或写入外部存储。 ##### 3.2.1 `collect` `collect` 算子用于将所有 RDD 的数据收集到 Driver 端,适用于小数据集。 ```scala val result = rdd.collect() ``` ##### 3.2.2 `count` `count` 算子用于统计 RDD 中元素的总数。 ```scala val total = rdd.count() ``` ##### 3.2.3 `take` `take` 算子用于从 RDD 中取出前 n 个元素。 ```scala val firstThree = rdd.take(3) ``` ##### 3.2.4 `foreach` `foreach` 算子用于对 RDD 中的每个元素执行某个操作,通常用于输出或写入外部系统。 ```scala rdd.foreach(println) ``` ##### 3.2.5 `saveAsTextFile` `saveAsTextFile` 算子用于将 RDD 的内容保存为文本文件。 ```scala rdd.saveAsTextFile("output_path") ``` --- #### 3.3 使用场景 - **数据清洗与预处理**:使用 `map`、`filter`、`flatMap` 等算子对原始数据进行格式转换和过滤。 - **数据聚合与统计**:使用 `reduceByKey`、`groupByKey` 等进行键值对的聚合操作。 - **数据合并与去重**:使用 `union` 和 `distinct` 对多个数据源进行合并和去重。 - **数据连接**:使用 `join` 对两个键值对 RDD 进行连接。 - **结果输出**:使用 `collect`、`foreach`、`saveAsTextFile` 将结果输出到控制台或文件系统。 --- #### 3.4 示例代码 ```python list1 = [1, 2, 3, 4, 5, 6, 7, 8] list2 = [5, 6, 7, 8, 9, 10] rdd1 = sc.parallelize(list1, 2) rdd2 = sc.parallelize(list2, 2) rdd3 = rdd1.union(rdd2) rdd4 = rdd3.distinct() rdd4.foreach(print) ``` 该代码展示了 `union` 和 `distinct` 的组合使用,先合并两个列表,再去除重复元素[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值