Spark---常用RDD算子

Spark之RDD转换算子和行动算子


文章目录

  • Spark之RDD转换算子和行动算子
  • RDD算子
  • RDD转换算子
    • Value 类型
      • map
      • mapPartitions
      • mapPartitionsWithIndex
      • flatMap
      • glom
      • groupBy
      • filter
      • sample
      • distinct
      • coalesce
        • coalesce shuffle操作
        • coalesce 扩大分区
      • sortBy
    • 双 Value 类型
      • intersection
      • union
      • subtract
      • zip
    • Key-Value类型
      • partitionBy
      • reduceByKey
      • groupByKey
      • aggregateByKey
      • foldByKey
      • combineByKey
      • sortByKey
      • join
      • leftOuterJoin
      • rightOuterJoin
      • cogroup
  • RDD 行动算子
      • reduce
      • collect
      • count
      • first
      • take
      • takeOrdered
      • aggregate
      • fold
      • countByKey
      • countByValue
      • save 相关算子
      • foreach


RDD算子

RDD算子分为两大类

转换算子:功能的补充和封装,将旧的RDD包装成新的RDD
例如 flatMap,map

行动算子:触发任务的调度和作业的执行
例如collect

RDD转换算子

RDD 根据数据处理方式的不同将算子整体上分为 Value 类型、双 Value 类型和 Key-Value类型

Value 类型

map

def map[U: ClassTag](f: T => U): RDD[U]
将处理的数据逐条进行映射转换,这里的转换可以是类型的转换,也可以是值的转换

    /**
     * map
     * 1,2,3,4  =>2,4,6,8
     *1.rdd的计算一个分区的数据是一个一个执行逻辑
     * 只有前面一个数据全部的逻辑执行完毕后,才会执行下一个数据
     * 分区内数据的执行是有序的
     * 2.不同分区数据计算是无序的
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    rdd.map(_*2).collect.foreach(x=>print(x+"\t"))

在这里插入图片描述

mapPartitions

def mapPartitions[U: ClassTag]( f: Iterator[T] => Iterator[U], preservesPartitioning: Boolean = false): RDD[U]
将待处理的数据以分区为单位发送到计算节点进行处理,这里的处理是指可以进行任意的处理,哪怕是过滤数据

    /**
     * mapPartitions
     * 可以以分区为单位进行数据转换操作
     * 但是会将整个分区的数据加载到内存进行引用
     * 如果处理完的数据是不会被释放掉,存在对象引用
     * 若遇到内存小,数据量大则会出现内存以内存溢出
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),2)
    val mapRdd: RDD[Int] = rdd.mapPartitions(
      iter => {
        println(">>>>>>>")
        iter.map(_ * 2)
      }
    )
    mapRdd.collect().foreach(println)

Spark---常用RDD算子_第1张图片

mapPartitionsWithIndex

def mapPartitionsWithIndex[U: ClassTag](f: (Int, Iterator[T]) => Iterator[U],preservesPartitioning: Boolean = false): RDD[U]
将待处理的数据以分区为单位发送到计算节点进行处理,这里的处理是指可以进行任意的处理,哪怕是过滤数据,在处理时同时可以获取当前分区索引

    /**
     * mapPartitionsWithIndex
     * 获取第二个分区内的数据
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),2)
    val mapRdd: RDD[Int] = rdd.mapPartitionsWithIndex(
      (index, iter) => {
        if (index == 1) {
          //保留迭代器
          iter
        } else {
          //Nil为空集合---即为空迭代器
          Nil.iterator
        }
      }
    )
    mapRdd.collect().foreach(println)

在这里插入图片描述

flatMap

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

    /**
     * flatMap 扁平映射
     *
     */
    val rdd: RDD[List[Int]] = sc.makeRDD(List(List(1, 2), List(3, 4)))
    val flatRdd: RDD[Int] = rdd.flatMap(
      list => {
        list
      }
    )
    flatRdd.collect().foreach(println)

Spark---常用RDD算子_第2张图片

glom

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

    /**
     * glom
     * List =>Int
     * Int =>Array
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4), 2)
    val glomRdd: RDD[Array[Int]] = rdd.glom()
    glomRdd.collect().foreach(x=>println(x.mkString(",")))

在这里插入图片描述

groupBy

def groupBy[K](f: T => K)(implicit kt: ClassTag[K]): RDD[(K, Iterable[T])]
将数据根据指定的规则进行分组, 分区默认不变,但是数据会被打乱重新组合,我们将这样的操作称之为 shuffle
极限情况下,数据可能被分在同一个分区中
一个组的数据在一个分区中,但是并不是说一个分区中只有一个组

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

在这里插入图片描述

filter

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

    /**
     * filter
     * 奇数留下,偶数去除
     *
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    val filterRdd: RDD[Int] = rdd.filter(_ % 2 != 0)
    filterRdd.collect().foreach(println)

在这里插入图片描述

sample

def sample(withReplacement: Boolean,fraction: Double, seed: Long = Utils.random.nextLong): RDD[T]
根据指定的规则从数据集中抽取数据

    /**
     * sample
     * 抽样
     * 抽取数据不放回(伯努利算法)
     * 第一个参数:抽取数据后是否将数据放回 true--放回 false--丢弃
     * 第二个参数:抽取的几率,范围在[0,1]之间,0--全不取;1--全取
     * 第三个参数:抽取数据时随机算法的种子 如果不传递第三个参数,那么使用的是当前系统时间
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
    //第一个参数表示,抽取数据后是否将数据放回 true--放回 false--丢弃
    val sampleRdd: RDD[Int] = rdd.sample(false, 0.4, 1)
    println(sampleRdd.collect().mkString(","))

在这里插入图片描述

    /**
     * 抽取数据放回(泊松算法)
     * 第一个参数:抽取的数据是否放回,true:放回;false:不放回
     * 第二个参数:重复数据的几率,范围大于等于 0.表示每一个元素被期望抽取到的次数
     * 第三个参数:随机数种子
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
    //第一个参数表示,抽取数据后是否将数据放回 true--放回 false--丢弃
    val sampleRdd: RDD[Int] = rdd.sample(true, 2)
    println(sampleRdd.collect().mkString(","))

在这里插入图片描述

distinct

def distinct()(implicit ord: Ordering[T] = null): RDD[T]
def distinct(numPartitions: Int)(implicit ord: Ordering[T] = null): RDD[T]
将数据集中重复的数据去重

    /**
     * distinct 去重
     * 
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4, 1, 2, 3, 4))
    val disRdd: RDD[Int] = rdd.distinct()
    disRdd.collect().foreach(println)

Spark---常用RDD算子_第3张图片

coalesce

def coalesce(numPartitions: Int, shuffle: Boolean = false,partitionCoalescer: Option[PartitionCoalescer] = Option.empty) (implicit ord: Ordering[T] = null) : RDD[T]
根据数据量缩减分区,用于大数据集过滤后,提高小数据集的执行效率
当 spark 程序中,存在过多的小任务的时候,可以通过 coalesce 方法,收缩合并分区,减少分区的个数,减小任务调度成本

    /**
     * coalesce 缩减分区
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4), 4)
    rdd.saveAsTextFile("out1")
    val newRdd: RDD[Int] = rdd.coalesce(2)
    newRdd.saveAsTextFile("output")

Spark---常用RDD算子_第4张图片

coalesce shuffle操作

防止出现数据倾斜问题

    /**
     * coalesce 缩减分区
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4,5,6), 3)
    // coalesce 方法默认情况下不会将分区的数据打乱重新组合
    //这种情况下缩减分区可以能导致数据不均衡,出现数据倾斜
    //如果想要让数据均衡,可以进行shuffle处理,传第二个参数true
    //val newRdd: RDD[Int] = rdd.coalesce(2)
    val newRdd: RDD[Int] = rdd.coalesce(2,true)
    newRdd.saveAsTextFile("output")

Spark---常用RDD算子_第5张图片

coalesce 扩大分区

需要使用shuffle操作
与repartition作用相同

    /**
     * coalesce 扩大分区
     * 与repartition作用相同
     * repartition底层使用 coalesce方法并且shuffle默认设为true
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4,5,6), 2)
    //coalesce 可以扩大分区,但是如果不进行shuffle操作,是没有意义,不起作用
    //所以如果想要扩大分区的效果,需要使用shuffle操作
    val newRdd: RDD[Int] = rdd.coalesce(3,true)
    newRdd.saveAsTextFile("output")

Spark---常用RDD算子_第6张图片
Spark---常用RDD算子_第7张图片

sortBy

def sortBy[K](f: (T) => K, ascending: Boolean = true,numPartitions: Int = this.partitions.length) (implicit ord: Ordering[K], ctag: ClassTag[K]): RDD[T]
该操作用于排序数据。在排序之前,可以将数据通过 f 函数进行处理,之后按照 f 函数处理的结果进行排序,默认为升序排列。排序后新产生的 RDD 的分区数与原 RDD 的分区数一致。中间存在 shuffle 的过程

    /**
     *  sortBy
     *  中间存在 shuffle 的过程
     *  可以根据指定的规则对数据源中的数据进行排序,默认升序
     *  第二个参数可以改变排序方式
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(("1", 1), ("11", 2), ("2", 3)), 2)
    val newRdd: RDD[(String, Int)] = rdd.sortBy(t => t._1.toInt)
    newRdd.collect().foreach(println)


    //改变排序方式
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(("1", 1), ("11", 2), ("2", 3)), 2)
    val newRdd: RDD[(String, Int)] = rdd.sortBy(t => t._1.toInt,false)
    newRdd.collect().foreach(println)
    

在这里插入图片描述
在这里插入图片描述

双 Value 类型

intersection

def intersection(other: RDD[T]): RDD[T]
对源 RDD 和参数 RDD 求交集后返回一个新的 RDD

    /**
     *   双value类型
     *   intersection
     *   交集
     *
     */
    val rdd1: RDD[Int] = sc.makeRDD(List(1,2,3,4))
    val rdd2: RDD[Int] = sc.makeRDD(List(3,4,5,6))
    val intRdd: RDD[Int] = rdd1.intersection(rdd2)
    intRdd.collect().foreach(println)

在这里插入图片描述

union

def union(other: RDD[T]): RDD[T]
对源 RDD 和参数 RDD 求并集后返回一个新的 RDD

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

在这里插入图片描述

subtract

def subtract(other: RDD[T]): RDD[T]
以一个 RDD 元素为主,去除两个 RDD 中重复元素,将其他元素保留下来。求差集

    /**
     * subtract
     * 差集
     */
    val rdd1: RDD[Int] = sc.makeRDD(List(1,2,3,4))
    val rdd2: RDD[Int] = sc.makeRDD(List(3,4,5,6))

    val rdd: RDD[Int] = rdd1.subtract(rdd2)
    println(rdd.collect().mkString(","))//1,2
    val rdd3: RDD[Int] = rdd2.subtract(rdd1)
    println(rdd3.collect().mkString(","))//5,6

在这里插入图片描述

zip

def zip[U: ClassTag](other: RDD[U]): RDD[(T, U)]
将两个 RDD 中的元素,以键值对的形式进行合并。其中,键值对中的 Key 为第 1 个 RDD中的元素,Value 为第 2 个 RDD 中的相同位置的元素

    /**
     * 拉链
     * 可以数据类型不一致
     * 两个数据源要求分区数量保持一致
     * 每一个分区的元素数量要保持一样
     */
    val rdd1: RDD[Int] = sc.makeRDD(List(1,2,3,4))
    val rdd2: RDD[Int] = sc.makeRDD(List(3,4,5,6))
    val rdd: RDD[(Int, Int)] = rdd1.zip(rdd2)
    println(rdd.collect().mkString(","))

在这里插入图片描述

Key-Value类型

partitionBy

def partitionBy(partitioner: Partitioner): RDD[(K, V)]
将数据按照指定 Partitioner 重新进行分区。Spark 默认的分区器是 HashPartitione

 /**
     *partitionBy
     * 根据指定的分区规则对数据进行重分区
     * 使用默认HashPartitioner分区器分区
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),2)
    val mapRdd: RDD[(Int, Int)] = rdd.map((_, 1))
    //RDD=>PairRDDFunctions
    //隐式转换
    mapRdd.partitionBy(new HashPartitioner(2)).saveAsTextFile("output")

Spark---常用RDD算子_第8张图片
在这里插入图片描述
在这里插入图片描述

reduceByKey

def reduceByKey(func: (V, V) => V): RDD[(K, V)]
def reduceByKey(func: (V, V) => V, numPartitions: Int): RDD[(K, V)]
可以将数据按照相同的 Key 对 Value 进行聚合

    /**
     * reduceByKey
     * 相同的key的数据进行value数据操作
     * scala语言中的聚合一般是两两聚合,
     * spark基于scala开发,所以spark聚合也是两两聚合
     * reduceByKey中如果数据只有一个,是不会参与运算的
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(("a", 1), ("a", 2), ("a", 3), ("b", 4)))
    val reRdd: RDD[(String, Int)] = rdd.reduceByKey((x, y) => {
      println(s"x=${x},y=${y}")
      x + y
    })
    reRdd.collect().foreach(println)

Spark---常用RDD算子_第9张图片

groupByKey

def groupByKey(): RDD[(K, Iterable[V])]
def groupByKey(numPartitions: Int): RDD[(K, Iterable[V])]
def groupByKey(partitioner: Partitioner): RDD[(K, Iterable[V])]
将数据源的数据根据 key 对 value 进行分组

    /**
     * groupByKey
     * 将数据源中的数据,相同key的数据分在一个组中,形成一个对偶元组
     * 元组中第一个元素就是key
     * 元组中第二个元素就是相同key的value集合
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(("a", 1), ("a", 2), ("a", 3), ("b", 4)))
    val groupRdd: RDD[(String, Iterable[Int])] = rdd.groupByKey()
    groupRdd.collect().foreach(println)

在这里插入图片描述

aggregateByKey

def aggregateByKey[U: ClassTag](zeroValue: U)(seqOp: (U, V) => U,combOp: (U, U) => U): RDD[(K, U)]
将数据根据不同的规则进行分区内计算和分区间计算

    //key---value类型
    /**
     *  aggregateByKey
     *  存在函数的柯里化 有两个参数列表
     *  第一个参数列表需要传递一个参数,表示初始值
     *          主要用于当碰见第一个key的时候和value进行分区计算
     *  第二个参数列表需要传递2个参数
     *          第一个参数表示分区内计算规则
     *          第二个参数表示分区间计算规则
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(("a", 1), ("a", 2), ("a", 3), ("a", 4)),2)
    // 取出每个分区内相同 key 的最大值然后分区间相加
    rdd.aggregateByKey(0)(
      (x,y) =>math.max(x,y),
      (x,y) =>x+y
    ).collect().foreach(println)

在这里插入图片描述

foldByKey

def foldByKey(zeroValue: V)(func: (V, V) => V): RDD[(K, V)]
当分区内计算规则和分区间计算规则相同时,aggregateByKey 就可以简化为 foldByKey

    /**
     *  foldByKey
     *  当分区内计算规则和分区间计算规则相同时,aggregateByKey 就可以简化为 foldByKey
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(
      ("a", 1), ("a", 2),("a", 3),
      ("b", 4), ("b",5),("a",6)
    ),2)
    val foldRdd: RDD[(String, Int)] = rdd.foldByKey(0)(_ + _)
    foldRdd.collect().foreach(println)

在这里插入图片描述

combineByKey

def combineByKey[C](createCombiner: V => C, mergeValue: (C, V) => C, mergeCombiners: (C, C) => C): RDD[(K, C)]
最通用的对 key-value 型 rdd 进行聚集操作的聚集函数(aggregation function)。类似于aggregate(),combineByKey()允许用户返回值的类型与输入不一致。

    /**
     *  combineByKey
     *  需要三个参数
     *  第一个参数:将相同key的第一个数据进行结构转换
     *  第二个参数:分区内的计算规则
     *  第三个参数:分区间的计算规则
     *
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(
      ("a", 1), ("a", 2),("b", 3),
      ("b", 4), ("b",5),("a",6)
    ),2)
    //获取相同key的平均值 =>(a,3)(b,4)
    val newRdd: RDD[(String, (Int, Int))] = rdd.combineByKey(
      //第一个参数
      v => (v,1),
        //第二个参数
        (t:(Int,Int),v)=>{
        (t._1 + v, t._2 + 1)
      },
      //第三个参数
      (t1:(Int,Int), t2:(Int,Int)) => {
        (t1._1 + t2._1, t1._2 + t2._2)
      }
    )
    val resutRdd: RDD[(String, Int)] = newRdd.mapValues {
      case (num, cnt) => {
        num / cnt
      }
    }
    resutRdd.collect().foreach(println)

在这里插入图片描述

sortByKey

def sortByKey(ascending: Boolean = true, numPartitions: Int = self.partitions.length) : RDD[(K, V)]
在一个(K,V)的 RDD 上调用,K 必须实现 Ordered 接口(特质),返回一个按照 key 进行排序的

    /**
     * sortByKey
     * true:字典升序
     * false:字典降序
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(("a", 1), ("b", 2), ("c", 3)))
    val sortRdd: RDD[(String, Int)] = rdd.sortByKey(true)
    sortRdd.collect().foreach(println)
    println("=================")
    val sortRdd1: RDD[(String, Int)] = rdd.sortByKey(false)
    sortRdd1.collect().foreach(println)

Spark---常用RDD算子_第10张图片

join

def join[W](other: RDD[(K, W)]): RDD[(K, (V, W))]
在类型为(K,V)和(K,W)的 RDD 上调用,返回一个相同 key 对应的所有元素连接在一起的(K,(V,W))的 RDD

    /**
     * join
     * 两个不同数据源的数据,相同key的value会连接在一起,形成元组
     * 如果两个数据源中key没有匹配上,那么数据不会出现在结果中
     * 如果两个数据源中key有多个相同的,会依次匹配,可能会出现笛卡尔积,数据量会几何增长,会导致性能降低
     */

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

在这里插入图片描述

leftOuterJoin

def leftOuterJoin[W](other: RDD[(K, W)]): RDD[(K, (V, Option[W]))]
类似于 SQL 语句的左外连接

    /**
     * leftOuterJoin
     *
     */

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

Spark---常用RDD算子_第11张图片

rightOuterJoin

右外连接

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

在这里插入图片描述

cogroup

def cogroup[W](other: RDD[(K, W)]): RDD[(K, (Iterable[V], Iterable[W]))]
在类型为(K,V)和(K,W)的 RDD 上调用,返回一个(K,(Iterable,Iterable))类型的 RDD

    /**
     * cogroup:connect+group
     * 分组连接
     * 最多可以连接三个
     */
    val rdd1: RDD[(String, Int)] = sc.makeRDD(List(
      ("a", 1), ("b", 2),//("c", 3)
    ))
    val rdd2: RDD[(String, Int)] = sc.makeRDD(List(
      ("a", 4), ("b", 5), ("c", 6)
    ))
    val coRdd: RDD[(String, (Iterable[Int], Iterable[Int]))] = rdd1.cogroup(rdd2)
    coRdd.collect().foreach(println)

在这里插入图片描述

RDD 行动算子

reduce

def reduce(f: (T, T) => T): T
聚集 RDD 中的所有元素,先聚合分区内数据,再聚合分区间数据

    /**
     * reduce
     * 数据源中的数据两两聚合
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    val i: Int = rdd.reduce(_ + _)
    println(i)

在这里插入图片描述

collect

def collect(): Array[T]
在驱动程序中,以数组 Array 的形式返回数据集的所有元素

    /**
     * 底层代码调用的是环境对象runJob方法
     * 底层代码中会创建ActiveJob,并提交执行
     *
     * collect
     * 方法会将不同分区的数据按照分区顺序采集到Driver端内存中,形成数据
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    val ints: Array[Int] = rdd.collect()
    println(ints.mkString(","))

在这里插入图片描述

count

def count(): Long
返回 RDD 中元素的个数

    /**
     * count
     * 数据源中的数据个数
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    val l: Long = rdd.count()
    println(l)

在这里插入图片描述

first

def first(): T
返回 RDD 中的第一个元素

    /**
     * first
     * 取数据源中第一个数据
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    val i: Int = rdd.first()
    println(i)

在这里插入图片描述

take

def take(num: Int): Array[T]
返回一个由 RDD 的前 n 个元素组成的数组

    /**
     * take
     * 取数据源中n个数据
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    val ints: Array[Int] = rdd.take(3)
    println(ints.mkString(","))

在这里插入图片描述

takeOrdered

def takeOrdered(num: Int)(implicit ord: Ordering[T]): Array[T]
返回该 RDD 排序后的前 n 个元素组成的数组

    /**
     * takeOrdered
     * 默认升序
     * 数据排序后取n个数据
     * 可以传第二个参数使得降序排序
     */
    val rdd: RDD[Int] = sc.makeRDD(List(4,2,3,1))
    val ints: Array[Int] = rdd.takeOrdered(3)
    println(ints.mkString(","))
    val ints1: Array[Int] = rdd.takeOrdered(3)(Ordering.Int.reverse)
    println(ints1.mkString(","))

在这里插入图片描述

aggregate

def aggregate[U: ClassTag](zeroValue: U)(seqOp: (U, T) => U, combOp: (U, U) => U): U
分区的数据通过初始值和分区内的数据进行聚合,然后再和初始值进行分区间的数据聚合

    /**
     * aggregate:初始值会参与分区计算,并且参与分区间的计算
     * 10+13+17=40
     * aggregateByKey:初始值只会参与分区内计算
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4),2)
    val result: Int = rdd.aggregate(10)(_ + _, _ + _)
    println(result)

在这里插入图片描述

fold

def fold(zeroValue: T)(op: (T, T) => T): T
折叠操作,aggregate 的简化版操作

    /**
     * fold
     * 分区内和分区间计算规则是相同的
     * 10+13+17=40
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4),2)
    val result: Int = rdd.fold(10)(_ + _)
    println(result)

在这里插入图片描述

countByKey

def countByKey(): Map[K, Long]
统计每种 key 的个数

    /**
     * countByKey
     * 统计每种 key 的个数
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(
      List(
        ("a", 1), ("a", 1), ("a", 5)
      ))
    val stringToLong: collection.Map[String, Long] = rdd.countByKey()
    println(stringToLong)

在这里插入图片描述

countByValue

统计每种value的个数

    /**
     * countByValue
     *
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4),2)
    val intToLong: collection.Map[Int, Long] = rdd.countByValue()
    println(intToLong)

在这里插入图片描述

save 相关算子

def saveAsTextFile(path: String): Unit
def saveAsObjectFile(path: String): Unit
def saveAsSequenceFile( path: String,codec: Option[Class[_ <: CompressionCodec]] = None): Unit
将数据保存到不同格式的文件中

    /**
     * saveAsTextFile
     * saveAsObjectFile
     * saveAsSequenceFile
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(
      List(
        ("a", 1), ("a", 1), ("a", 5)
      ),3)
    rdd.saveAsTextFile("output")
    rdd.saveAsObjectFile("output1")
    //要求数据格式必须是k-v类型
    rdd.saveAsSequenceFile("output2")

Spark---常用RDD算子_第12张图片

foreach

def foreach(f: T => Unit): Unit = withScope {
val cleanF = sc.clean(f)
sc.runJob(this, (iter: Iterator[T]) => iter.foreach(cleanF))
}
分布式遍历 RDD 中的每一个元素,调用指定函数

    /**
     * foreach
     *
     */
    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    //先采集
    //foreach是Driver端内集合的循环遍历方法
    rdd.collect().foreach(println)
    println("==========")
    //foreach是Executor端数据打印
    rdd.foreach(println)

Spark---常用RDD算子_第13张图片

你可能感兴趣的:(Spark,spark,scala,大数据)