RDD的Transformation(转换算子)

RDD的Transformation(转换算子)

RDD整体上分为Value类型、双Value类型和Key-Value类型

1 value类型

创建包名:com.xiao_after.value

1.1 map()映射

1)函数签名:

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

2)功能说明:参数 f 是一个函数,它可以接收一个参数。当某个RDD执行map方法时,

会遍历该RDD中的每一个数据项,并依次应用 f 函数,从而产生一个新的RDD。即,这个

新的RDD中的每一个元素都是原来RDD中每一个元素依次应用 f 函数而得到的。

3)需求说明:创建一个1-4数组的RDD,两个分区,将所有元素*2形成新的RDD

4)具体实现

package com.xiao_after.value

import org.apache.spark.{
   SparkConf, SparkContext}
import org.apache.spark.rdd.RDD

/**
 * @author xiaohu
 * @create 2020-09-24 21:06
 */
object value01_map {
   
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkConf并设置App名称
    val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")

    //2.创建SparkContext,该对象是提交Spark App的入口
    val sc: SparkContext = new SparkContext(conf)

    //3.具体业务逻辑
    //3.1 创建一个rdd
    val rdd: RDD[Int] = sc.makeRDD(1 to 4, 2)

    //3.2 调用map方法,每个元素乘以2
    val rdd1: RDD[Int] = rdd.map(_ * 2)

    //3.3 遍历打印输出rdd1
    rdd1.collect().foreach(println)

    //4.关闭连接
    sc.stop()

  }
}

5)输出结果

2
4
6
8
1.2 mapPartitions()以分区为单位执行Map

1)函数签名:

def mapPartitions[U: ClassTag](f: Iterator[T] => Iterator[U]

2)功能说明:Map是依次处理一个元素,而mapPartitions一次处理一个分区数据。

3)需求说明:创建一个RDD,4个元素,2个分区,使每个元素组成新的RDD。

4)具体实现

package com.xiao_after.value

import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

/**
 * @author xiaohu
 * @create 2020-09-24 21:16
 */
object value02_mapPartitions {
   
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkConf并设置App名称
    val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")

    //2.创建SparkContext,该对象是提交Spark App的入口
    val sc: SparkContext = new SparkContext(conf)

    //3具体业务逻辑
    //3.1 创建一个rdd
    val rdd: RDD[Int] = sc.makeRDD(1 to 4,2)

    //3.2 调用mapPartitions方法,每个元素乘以2
    val rdd1: RDD[Int] = rdd.mapPartitions(_.map(_*2))

    //3.3 遍历打印rdd1中的数据
    rdd1.collect().foreach(println)

    //4.关闭连接
    sc.stop()
    
  }
}

5)输出结果

2
4
6
8
1.3 map()和mapPartitions()区别

1)map():每次处理一条数据;

2)mapPartitions():每次处理一个分区的数据,这个分区的数据处理完后,元RDD分区

中的数据才能释放,可能导致OOM;

3)开发经验:当内存空间较大的时候,建议使用 mapPartitions(),以提高处理效率。

1.4 mapPartitionsWithIndex()带分区号

1)函数签名

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

2)功能说明:类似于mapPartitions,比mapPartitions多一个整数参数表示分区号

3)需求说明:创建一个RDD,使每个元素跟所在分区号形成一个元组,组成一个新的

RDD

4)具体实现

package com.xiao_after.value

import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

/**
 * @author xiaohu
 * @create 2020-09-24 21:07
 */
object value03_mapPartitionsWithIndex {
   
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkConf并设置App名称
    val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")

    //2.创建SparkContext,该对象是提交Spark App的入口
    val sc: SparkContext = new SparkContext(conf)

    //3.具体业务逻辑
    //3.1 创建一个RDD
    val rdd: RDD[Int] = sc.makeRDD(1 to 4, 2)

    //3.2 使每个元素跟所在分区号形成一个元组,组成一个新的RDD
    val rdd1: RDD[(Int, Int)] = rdd.mapPartitionsWithIndex((index, items) => {
   
      items.map((index, _))
    })

    //3.3 遍历打印rdd1的数据
    rdd1.collect().foreach(println)

    //4.关闭连接
    sc.stop()

  }
}

5)输出结果

(0,1)
(0,2)
(1,3)
(1,4)
1.5 flatMap()扁平化

1)函数签名

  def flatMap[U: ClassTag](f: T => TraversableOnce[U]): RDD[U] 

2)功能说明

与map操作类似,将RDD中的每一个元素通过应用f函数依次转换为新的元素,并封装到

RDD中。区别:在flatMap操作中,f函数的返回值是一个集合,并且会将每一个该集合中

的元素拆分出来放到新的RDD中;

3)需求说明:创建一个集合,集合里面存储的还是子集合,把所有子集合中数据取出放

入到一个大的集合中;

4)具体实现

package com.xiao_after.value

import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

/**
 * @author xiaohu
 * @create 2020-09-24 22:55
 */
object value04_flatMap {
   
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkConf并设置App名称
    val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")

    //2.创建SparkContext,该对象是提交Spark App的入口
    val sc: SparkContext = new SparkContext(conf)

    //3.具体业务逻辑
    //3.1 创建一个RDD
    val rdd: RDD[List[Int]] = sc.makeRDD(List(List(1, 2), List(3, 4), List(5, 6), List(7)), 2)

    //3.2 把所有子集合中数据取出放入到一个大的集合中
    val rdd1: RDD[Int] = rdd.flatMap(list => list)

    //3.3 遍历打印rdd1的数据
    rdd1.collect().foreach(println)


    //4.关闭连接
    sc.stop()
  }
}

5)运行结果

1
2
3
4
5
6
7
1.6 glom()分区转换数组

1)函数签名

def glom(): RDD[Array[T]]

2)功能说明:

​ 该操作将RDD中每一个分区变成一个数组,并放置在新的RDD中,数组中元素的类型与

原分区中元素类型一致

3)需求说明:创建一个2个分区的RDD,并将每个分区的数据放到一个数组,求出每个

分区的最大值

4)具体实现

package com.xiao_after.value

import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

/**
 * @author xiaohu
 * @create 2020-09-24 22:56
 */
object value05_glom {
   
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkConf并设置App名称
    val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")

    //2.创建SparkContext,该对象是提交Spark App的入口
    val sc: SparkContext = new SparkContext(conf)

    //3.具体业务逻辑
    //3.1 创建一个RDD
    val rdd: RDD[Int] = sc.makeRDD(1 to 4, 2)

    //3.2 求出每个分区的最大值
    val rdd1: RDD[Int] = rdd.glom().map(_.max)

    //3.3 求出所有分区的最大值的和 2 + 4
    println(rdd1.collect().sum)

    //4.关闭连接
    sc.stop()

  }
}

5)运行结果

6
1.7 groupBy()分组

1)函数签名:

  def groupBy[K](f: T => K)(implicit kt: ClassTag[K]): RDD[(K, Iterable[T])]

2)功能说明:分组,按照传入函数的返回值进行分组。将相同的 key 对应的值放入一个

迭代器

3)需求说明:创建一个RDD,按照元素模以2的值进行分组

4)具体实现

package com.xiao_after.value

import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

/**
 * @author xiaohu
 * @create 2020-09-24 22:56
 */
object value06_groupby {
   
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkConf并设置App名称
    val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")

    //2.创建SparkContext,该对象是提交Spark App的入口
    val sc: SparkContext = new SparkContext(conf)

    //3.具体业务逻辑
    //3.1 创建一个RDD
    val rdd: RDD[Int] = sc.makeRDD(1 to 4, 2)

    //3.2 将每个分区的数据放到一个数组并收集到Driver端打印
    rdd.groupBy(_ % 2).collect().foreach(println)
      
    println("--------------------------")

    //3.3 再创建一个RDD
    val rdd1: RDD[String] = sc.makeRDD(List("hello", "hive", "hadoop", "spark", "scala"))

    //3.4 按照首字母第一个单词相同分组
    rdd1.groupBy(str => str.substring(0, 1)).collect().foreach(println)

    //4.关闭连接
    sc.stop()

  }
}

5)运行结果

(0,CompactBuffer(2, 4))
(1,CompactBuffer(1, 3))
--------------------------
(s,CompactBuffer(spark, scala))
(h,CompactBuffer(hello, hive, hadoop))

注:groupBy会存在shuffle过程;

shuffle:将不同的分区数据进行打乱重组的过程;

shuffle一定会落盘。可以在local模式下执行程序,通过4040看效果。

1.8 GroupBy之WordCount

1)需求说明:创建一个RDD,使用 GroupBy 实现 WordCount 功能

2)具体实现:

package com.xiao_after.value

import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

/**
 * @author xiaohu
 * @create 2020-09-24 23:37
 */
object value07_groupby_wordcount {
   
  def main(args: Array[String]): Unit = {
   
    //1.创建SparkConf并设置App名称
    val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")

    //2.创建SparkContext,该对象是提交Spark App的入口
    val sc: SparkContext = new SparkContext(conf)

    //3.具体业务逻辑
    //3.1 创建一个RDD
    val strList: List[String] = List("Hello Scala", "Hello Spark", "Hello World")
    val rdd = sc.makeRDD(strList)

    //3.2 将字符串拆分成一个一个的单词
    val rdd1: RDD[String] = rdd.flatMap(_.split(" "))

    //3.3 将单词结果进行转换,(word) => (word,1)
    val rdd2: RDD[(String, Int)] = rdd1.map((_, 1))

    //3.4 将转换结构后的数据分组
    val rdd3: RDD[(String, Iterable[(String
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值