Spark中filter、map、flatMap、union、groupByKey、reduceByKey等共享变量示例 方法记录

博客介绍了Spark创建RDD的方式,包括读取外部数据集和并行化集合,还提及slices数目设置。阐述了Transformation和Action算子,如map、filter等。介绍了spark shell本地测试中各算子用法,最后讲解了Spark的共享变量,如Broadcast Variable和Accumulator。

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

Spark提供了两种创建RDD的方式:读取外部数据集,以及在驱动器程序中对一个集合进行并行化。

在驱动器程序中对一个集合进行并行化的方式有两种:parallelize()和makeRDD()。

创建并行集合的一个重要参数,是slices的数目(例子中是numMappers),它指定了将数据集切分为几份

一般来说,Spark会尝试根据集群的状况,来自动设定slices的数目。当让,也可以手动的设置它,通过parallelize方法的第二个参数。

  • map()、filter()、join() 等算子称为 Transformation,它们输入一个或多个 RDD,输出一个 RDD。
  • collect()、count()、save() 等算子称为 Action,它们通常是将数据收集起来返回

 map(func) :返回一个新的分布式数据集,由每个原元素经过func函数转换后组成 
spark shell本地测试:

  val numbers = Array(1, 2, 3, 4, 5)
    val numberRDD = sc.parallelize(numbers, 1)  
    val multipleNumberRDD = numberRDD.map ( num => num * 2 )
    multipleNumberRDD.foreach ( num => println(num) ) 


 filter(func) : 返回一个新的数据集,由经过func函数后返回值为true的原元素组成

 val numbers = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    val numberRDD = sc.parallelize(numbers, 1)
    val evenNumberRDD = numberRDD.filter { num => num % 2 == 0 }


flatMap(func) : 类似于map,但是每一个输入元素,会被映射为0到多个输出元素(因此,func函数的返回值是一个Seq,而不是单一元素) 

val lineArray = Array("hello you", "hello me", "hello world")  
    val lines = sc.parallelize(lineArray, 1)
    val words = lines.flatMap { line => line.split(" ") }   
    words.foreach { word => println(word) }


union(otherDataset) : 返回一个新的数据集,由原数据集和参数联合而成 
groupByKey([numTasks]) :在一个由(K,V)对组成的数据集上调用,返回一个(K,Seq[V])对的数据集。注意:默认情况下,使用8个并行任务进行分组,你可以传入numTask可选参数,根据数据量设置不同数目的Task

 val scoreList = Array(Tuple2("class1", 80), Tuple2("class2", 75),Tuple2("class1", 90), Tuple2("class2", 60))
    val scores = sc.parallelize(scoreList, 1)  
    val groupedScores = scores.groupByKey() 
     groupedScores.foreach(score => { 
      println(score._1); 
      score._2.foreach { singleScore => println(singleScore) };
      println("=============================")  })


reduceByKey(func, [numTasks]) : 在一个(K,V)对的数据集上使用,返回一个(K,V)对的数据集,key相同的值,都被使用指定的reduce函数聚合到一起。和groupbykey类似,任务的个数是可以通过第二个可选参数来配置的。在实际开发中,能使reduceByKey实现的就不用groupByKey

val scoreList = Array(Tuple2("class1", 80), Tuple2("class2", 75),Tuple2("class1", 90), Tuple2("class2", 60))
    val scores = sc.parallelize(scoreList, 1)  
    val totalScores = scores.reduceByKey(_ + _)  
    totalScores.foreach(classScore => println(classScore._1 + ": " + classScore._2))  


join(otherDataset, [numTasks]) :在类型为(K,V)和(K,W)类型的数据集上调用,返回一个(K,(V,W))对,每个key中的所有元素都在一起的数据集

 val studentList = Array(
        Tuple2(1, "leo"),
        Tuple2(2, "jack"),
        Tuple2(3, "tom"));
   val scoreList = Array(
        Tuple2(1, 100),
        Tuple2(2, 90),
        Tuple2(3, 60));
    val students = sc.parallelize(studentList);
    val scores = sc.parallelize(scoreList);
    val studentScores = students.join(scores)  
    studentScores.foreach(studentScore => { 
      println("student id: " + studentScore._1);
      println("student name: " + studentScore._2._1)
      println("student socre: " + studentScore._2._2)  
      println("=======================================")  
    })  


 

 groupWith(otherDataset, [numTasks]) : 在类型为(K,V)和(K,W)类型的数据集上调用,返回一个数据集,组成元素为(K, Seq[V], Seq[W]) Tuples。这个操作在其它框架,称为CoGroup 
cartesian(otherDataset) : 笛卡尔积。但在数据集T和U上调用时,返回一个(T,U)对的数据集,所有元素交互进行笛卡尔积。 
repartition():重新分区,当数据处理到最后剩下很少的数据集时,可以使用repartition()进行重新分区

reduce(func) : 通过函数func聚集数据集中的所有元素。Func函数接受2个参数,返回一个值。这个函数必须是关联性的,确保可以被正确的并发执行

val numberArray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    val numbers = sc.parallelize(numberArray, 1)  
    val sum = numbers.reduce(_ + _)  
    println(sum)
//结果55 

collect() : 在Driver的程序中,以数组的形式,返回数据集的所有元素。这通常会在使用filter或者其它操作后,返回一个足够小的数据子集再使用

val numberArray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    val numbers = sc.parallelize(numberArray, 1)  
    val doubleNumbers = numbers.map { num => num * 2 }  
    val doubleNumberArray = doubleNumbers.collect()
    for(num <- doubleNumberArray) {
      println(num)  
    }
//结果
2
4
6
8
10
12
14
16
18
20

count() : 返回数据集的元素个数

val numberArray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    val numbers = sc.parallelize(numberArray, 1)  
    val count = numbers.count()
    println(count) 
//结果 10

take(n) : 返回一个数组,由数据集的前n个元素组成。注意,这个操作目前并非在多个节点上,并行执行,而是Driver程序所在机器,单机计算所有的元素(Gateway的内存压力会增大,需要谨慎使用)

val numberArray = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    val numbers = sc.parallelize(numberArray, 1)  
    val top3Numbers = numbers.take(3)
    for(num <- top3Numbers) {
      println(num)  
    }
//1,2,3

first() : 返回数据集的第一个元素(类似于take(1)) 
saveAsTextFile(path) : 将数据集的元素,以textfile的形式,保存到本地文件系统,hdfs或者任何其它hadoop支持的文件系统。Spark将会调用每个元素的toString方法,并将它转换为文件中的一行文本 
saveAsSequenceFile(path) : 将数据集的元素,以sequencefile的格式,保存到指定的目录下,本地系统,hdfs或者任何其它hadoop支持的文件系统。RDD的元素必须由key-value对组成,并都实现了Hadoop的Writable接口,或隐式可以转换为Writable(Spark包括了基本类型的转换,例如Int,Double,String等等) 
foreach(func) : 在数据集的每一个元素上,运行函数func。这通常用于更新一个累加器变量,或者和外部存储系统做交互
 

共享变量示例 

Spark提供的Broadcast Variable是只读的,可以通过调用SparkContext的broadcast()方法来针对某个变量创建广播变量。每个节点可以使用广播变量的value()方法来获取值。

val factor = 3
   val factorBroadcast = sc.broadcast(factor)

   val arr =Array(1,2,3,4,5)
   val rdd = sc.parallelize(arr)
   val mutiRdd = rdd.map(num => num*factorBroadcast.value)
   mutiRdd.foreach(num => println(num))
//结果
3
6
9
12
15

Spark提供的Accumulator,主要用于多个节点对一个变量进行共享的操作,task只能对Accumulator进行累加操作,不能读取它的值,只有Driver程序可以读取

val sumAccumulator = sc.accumulator(0)

    val arr = Array(1,2,3,4,5)
    val rdd = sc.parallelize(arr)
    rdd.foreach(num => sumAccumulator +=num)
    println(sumAccumulator.value)
//结果 15

 

### Spark RDD 集合操作方法 Spark RDD 提供了丰富的集合操作方法,用于对分布式数据集进行转换和行动操作。以下是常见的集合操作方法: #### 转换操作(Transformation) - **map(func)**: 对 RDD 中的每个元素应用函数 `func`,并将结果返回为新的 RDD[^5]。 - **filter(func)**: 根据布尔函数 `func` 筛选 RDD 中的元素,返回满足条件的元素组成的新的 RDD[^5]。 - **flatMap(func)**: 类似于 `map`,但将结果展平为单个 RDD[^2]。 - **union(otherRDD)**: 返回两个 RDD 的并集[^4]。 - **intersection(otherRDD)**: 返回两个 RDD 的交集[^4]。 - **subtract(otherRDD)**: 返回当前 RDD 中不在另一个 RDD 中的元素[^4]。 - **distinct([numPartitions])**: 返回去重后的 RDD,可指定分区数量[^4]。 #### 行动操作(Action) - **collect()**: 将 RDD 的所有元素收集到驱动程序中,以数组形式返回[^5]。 - **count()**: 返回 RDD 中的元素总数[^3]。 - **take(n)**: 返回 RDD 的前 n 个元素。 - **reduce(func)**: 使用二元函数 `func` 对 RDD 的所有元素进行聚合操作。 - **foreach(func)**: 对 RDD 的每个元素应用函数 `func`,通常用于副作用操作[^5]。 --- ### sortBy 方法的三个参数 `sortBy` 是 Spark RDD 的一个转换操作方法,用于对 RDD 的元素进行排序。该方法具有以下三个参数: #### 参数 1:排序函数 第一个参数是一个函数,用于定义排序的关键字段。这个函数会作用于 RDD 的每个元素,返回一个值作为排序依据[^6]。 ```python # 示例:按元素大小升序排序 rdd = sc.parallelize([5, 3, 8, 1]) sorted_rdd = rdd.sortBy(lambda x: x) ``` #### 参数 2:升序标志 第二个参数是一个布尔值,用于指定排序顺序。如果设置为 `True`(默认值),则按升序排序;如果设置为 `False`,则按降序排序[^6]。 ```python # 示例:按元素大小降序排序 sorted_rdd_desc = rdd.sortBy(lambda x: x, ascending=False) ``` #### 参数 3:分区数量 第三个参数是可选的,用于指定排序后的 RDD 的分区数量。通过调整分区数量,可以优化性能或减少 Shuffle 操作带来的开销。如果未指定此参数,则默认使用 RDD 的当前分区数量[^6]。 ```python # 示例:按元素大小升序排序,并指定分区数量为 4 sorted_rdd_with_partitions = rdd.sortBy(lambda x: x, ascending=True, numPartitions=4) ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值