Spark RDD算子示例

本文详细介绍了Spark中的基本操作,包括转换算子如map、mapPartitions、flatMap、filter、sample、groupBy等,以及行动算子如reduce、collect、count、first。这些操作在处理RDD时起到关键作用,涉及数据转换、过滤、聚合等功能。

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

目录

一.算子的分类

转换算子(lazy):

行动算子(no-lazy):

二.转换算子:

Value类型:

map

mapPartitions

mapPartitionsWithIndex

flatMap

glom

groupBy

filter

sample

 distinct

coalesce

repartition

sortBy

双Value类型:

intersection

union

subtract

zip

k-v类型

partitionBy

reduceByKey

groupByKey

aggregateByKey

foldByKey

combineByKey

sortByKey

join

leftOuterJoin

cogroup

三、常用行动算子

reduce

collect

count

first

take

takeOrdered

aggregate

fold

countByKey

countByValue

save 相关算子

foreach

一.算子的分类

  • 在Spark中,算子是指用于处理RDD(弹性分布式数据集)的基本操作。算子可以分为两种类型:转换算子和行动算子。

转换算子(lazy):

转换算子是将一个RDD转换为另一个RDD的操作,不会立即执行,而是创建一个新的RDD,以记录转换的方式和参数,然后等待后续的行动算子触发计算。

行动算子(no-lazy):

行动算子是触发计算并返回结果的操作。它们会立即对RDD进行计算,然后将结果返回给驱动程序或存储到文件系统等。

二.转换算子:

Value类型:

map

def map[U: ClassTag](f: T => U): RDD[U] = withScope

将处理的数据逐条进行映射转换,这里的转换可以是类型的转换,也可以是值的转换

map将原来RDD的每个数据项通过map中的用户自定义函数f映射转变为一个新的元素。源码中的map算子相当于初始化一个RDD,新RDD叫做MappedRDD

 val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
    val sc: SparkContext = new SparkContext(conf)

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

    println(rdd.map(x => x * 2).collect().mkString(","))
    sc.stop()
    // 结果:2,4,6,8

mapPartitions

def mapPartitions[U: ClassTag](f: Iterator[T] => Iterator[U], preservesPartitioning: Boolean = false): RDD[U]

可以以分区为单位进行数据处理操作,这里的处理是指可以进行任意的处理,哪怕是过滤数据。但是会将整个分区的数据加载到内存中引用,处理完的数据是不会被释放掉,存在对象的引用,在内存较小,数据量较大的情况下会出现内存溢出(OOM)   

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
    val sc: SparkContext = new SparkContext(conf)

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

    val dataRDD1: RDD[Int] = rdd.mapPartitions(
      datas => {
      //几个分区就会打印几次>>>>>>>>>>>>>
        println(">>>>>>>>>>>>>")
        datas.map(_*2)
      }
    )
    println(dataRDD1.collect().mkString(","))
    sc.stop()
    //>>>>>>>>>>>>>
        //>>>>>>>>>>>>>
        //2,4,6,8

map与mapPartitions区别:

数据处理
map算子是分区内一个数据一个数据的执行
mapPartitions算子是以分区为单位进行批处理操作。
功能
map算子主要目的是将数据源中的数据进行转换和改变。不会减少或增多数据
mapPartitions算子需要传递一个迭代器,返回一个迭代器,没有要求元素的个数保持不变,可以增加或减少数据
性能
map算子类似于串行操作,性能较低
mapPartitions算子类似于批处理,性能较高。

mapPartitionsWithIndex

def mapPartitionsWithIndex[U: ClassTag](f: (Int, Iterator[T]) =>Iterator[U],preservesPartitioning: Boolean = false): RDD[U]

将待处理的数据以分区为单位发送到计算节点进行处理,这里的处理是指可以进行任意的处
理,哪怕是过滤数据,在处理时同时可以获取当前分区索引。

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
    val sc: SparkContext = new SparkContext(conf)

    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),2)
//     获取数据与所对应的分区
    val mapRdd: RDD[(Int, Int)] = rdd.mapPartitionsWithIndex(
      (index, datas) => {
        datas.map((index, _))
      }
    )
    println(mapRdd.collect.mkString(","))
    sc.stop()

flatMap

def flatMap[U: ClassTag](f: T => TraversableOnce[U]): RDD[U]
将处理的数据进行扁平化后再进行映射处理,所以算子也称之为扁平映射   

 val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
    val sc: SparkContext = new SparkContext(conf)

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

    val flatRdd: RDD[Int] = rdd.flatMap(
      list => {
        list
      }
    )
    println(flatRdd.collect.mkString(",")) // 1,2,3,4
    val rdd1: RDD[String] = sc.makeRDD(List("hello world", "hello spark"))
    val flatRdd1: RDD[String] = rdd1.flatMap(
      str => str.split(" ")
    )
    println(flatRdd1.collect.mkString(",")) //hello,world,hello,spark
    sc.stop()

glom

def glom(): RDD[Array[T]]
将同一个分区的数据直接转换为相同类型的内存数组进行处理,分区不变

 val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
    val sc: SparkContext = new SparkContext(conf)
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4), 2)

    val glomRdd: RDD[Array[Int]] = rdd.glom()

    glomRdd.collect.foreach(data => println(data.mkString(",")))

    sc.stop()

groupBy

**def groupBy[K](f: T => K)(implicit kt: ClassTag[K]): RDD[(K, Iterable[T])] **
将数据源中的每一个数据进行分组判断,根据返回的分组key进行分组,相同的key值的数据会放置一个组中。

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
    val sc: SparkContext = new SparkContext(conf)

    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),2)
//    groupby会将数据源中的每一个数据进行分组判断,根据返回的分组key进行分组,相同的key值的数据会放置一个组中。
    val groupByRdd: RDD[(Int, Iterable[Int])] = rdd.groupBy(
      _ % 2
    )
    groupByRdd.collect.foreach(println) //    (0,CompactBuffer(2, 4))
                                        //(1,CompactBuffer(1, 3))

    val rdd1: RDD[String] = sc.makeRDD(List("hello","hi","spark","sqoop"),2)
    //    
    val groupByRdd1: RDD[(String, Iterable[String])] = rdd1.groupBy(
      _.substring(0, 1)
    )
    groupByRdd1.collect.foreach(println)    //(h,CompactBuffer(hello, hi))
                                            //(s,CompactBuffer(spark, sqoop))
    sc.stop()

filter

**def filter(f: T => Boolean): RDD[T] **
将数据根据指定的规则进行筛选过滤,符合规则的数据保留,不符合规则的数据丢弃。当数据进行筛选过滤后,分区不变,但是分区内的数据可能不均衡,生产环境下,可能会出现数据倾斜。   

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
    val sc: SparkContext = new SparkContext(conf)

    val rdd: RDD[Int] 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值