数值类型转换算子

1.map算子

  • 定义: map(fun)函数
  • 解释: 将RDD的每一个元素通过fun函数计算得到一个新的结果,新的结果我们会组合成为一个新的RDD
  • 特别注意:一对一场景下,RDD的每一条数据对应新的RDD的中一条数据
  • 案例:
def mapOper(sc: SparkContext): Unit = {
  println("----------------map1开始------------------")
  val rdd = sc.makeRDD(Array(1, 2, 3, 4, 5, 0), 1)
  val map = rdd.map(_ * 3)
  map.foreach(println(_)) // 结果: 3  6  9  12  15  0
  println("----------------map1结束------------------")

  println("----------------map2开始------------------")
  val rdd2 = sc.makeRDD(Array("hbase", "flink", "kafka"))
  val word = rdd2.map((_, 1))
  word.foreach(println(_)) // 结果: (hbase,1)  (flink,1)  (kafka,1)
  println("----------------map2结束------------------")
}

2.filter过滤算子

  • 定义: filter(fun)算子
  • 解释:将RDD中每一个元素通过fun函数计算得到一个boolean类型的返回值,如果返回值为true保留数据
  • 特别注意:如果返回值为false,那么数据就舍弃 得到的新的RDD的类型和旧的RDD类型一样的
  • 案例:
def filterOper(sc: SparkContext): Unit = {
  println("----------------filter开始------------------")
  /**
   * 1 to 100 是scala中Seq集合的一种创建语法
   */
  val rdd = sc.makeRDD(1 to 10)
  val filter = rdd.filter((num: Int) => {
    if (num % 2 == 0) {
      true
    } else {
      false
    }
  })
  filter.foreach(println(_)) // 结果: 2  6  4  8  10
  println("----------------filter结束------------------")
}

3.flatMap压扁算子

  • 定义:flatMap(fun)算子
  • 解释:原先的RDD一条数据经过flatMap算子操作返回一个集合数据,集合数据中每一条数据就是新的RDD中的数据
  • 特别注意:一对多
  • 案例:
def flatMap(sc: SparkContext): Unit = {
  println("----------------flatMap开始------------------")
  val rdd = sc.makeRDD(Array("i am people", "dog is an animal"))
  val flatmap = rdd.flatMap((str: String) => {
    val word: Array[String] = str.split(" ")
    word
  })
  flatmap.foreach(println(_)) // 结果: i  am  people  dog  is  an  animal
  println("----------------flatMap结束------------------")
}
区别
map 输入一条数据,就输出一条数据
flatMap 输入一条数据,按一定的规则输出多条数据

4.mapPartitions

  • 定义:mapPartitions(fun)算子
  • 解释:和map算子函数含义一致,都是一个分区数据经过fun函数得到一个新的分区数据结果,新的结果组成新的RDD
  • 案例:
def mapPartitionsOper(sc: SparkContext): Unit = {
  println("----------------mapPartitions开始------------------")
  val rdd: RDD[Int] = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8), 5)
  val mapPartitions = rdd.mapPartitions((list: Iterator[Int]) => {
    val listBuffer: ListBuffer[Int] = ListBuffer()
    for (num <- list) {
      println(s"处理的分区数据是 $num")
      listBuffer.append(num * 3)
    }
    listBuffer.iterator
  })
  /*
    处理的分区数据是 1
    处理的分区数据是 2
    3
    处理的分区数据是 3
    6
    9
    处理的分区数据是 4
    12
    处理的分区数据是 5
    处理的分区数据是 6
    15
    18
    处理的分区数据是 7
    处理的分区数据是 8
    21
    24
  */
  mapPartitions.foreach(println(_))
  println("----------------mapPartitions结束------------------")
}
区别
map 每条数据都操作一次
mapPartitions 对每一分区数据操作一次

5.mapPartitionsWithIndex

  • 定义:mapPartitionsWithIndex(fun)算子
  • 解释:一次处理一个分区的数据,最后返回一个迭代器,附带传入一个分区索引
    fun函数输入参数类型是一个2元组(Int,Iterator[T])=>Iterator[U] :RDD[U]
  • 案例:
def mapPartitionsWithIndexOper(sc: SparkContext): Unit = {
  println("----------------mapPartitionsWithIndex开始------------------")
  val rdd: RDD[Int] = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8), 5)
  val mapPartitionsWithIndex: RDD[Int] = rdd.mapPartitionsWithIndex((index: Int, iterator: Iterator[Int]) => {
    val listBuffer: ListBuffer[Int] = ListBuffer()
    for (num <- iterator) {
      println(s"分区为 $index , 分区的数据为 $num ")
      listBuffer.append(num)
    }
    listBuffer.iterator
  })
  /*
    分区为 1 , 分区的数据为 2 
    分区为 0 , 分区的数据为 1 
    分区为 1 , 分区的数据为 3 
    1
    2
    3
    分区为 2 , 分区的数据为 4 
    4
    分区为 3 , 分区的数据为 5 
    分区为 3 , 分区的数据为 6 
    5
    6
    分区为 4 , 分区的数据为 7 
    分区为 4 , 分区的数据为 8 
    7
    8
  */
  mapPartitionsWithIndex.foreach(println((_)))
  println("----------------mapPartitionsWithIndex结束------------------")
}

总结

如果要实现将一个RDD数据集中每一条数据转换成为一个新的RDD数据集中记录,
可以使用map、mapPartitions、mapPartitiosWithIndex三种方式实现
一般我们建议使用mapPartitions、mapPartitiosWithIndex 这样的效率比较高点

6.sample

  • 定义:sample(withReplacement, fraction, seed):RDD[T] 抽样算子
    withReplacement:Boolean 是否放回抽样 true放回抽样,false代表不放回抽象
    fraction:Double 如果是放回抽样 整数代表同一个数据期望被抽中几次 如果是不放回抽样,0-1之间的小数,代表的抽取比例
    seed 种子 不用写(默认值) 抽样底层有算法,
  • 解释:抽样一部分数据进行处理分析(每个分区都会抽取数据)
  • 案例:
def sampleOper(sc: SparkContext): Unit = {
  println("----------------sample开始------------------")
  val rdd: RDD[Int] = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3), 4)
  val sample = rdd.sample(false, 0.5)
  val mapPartitionsWithIndex: RDD[Int] = sample.mapPartitionsWithIndex((index: Int, data: Iterator[Int]) => {
    println(s"分区为 $index , 数据为 ${data.mkString("=")}")
    data
  })
  // 下面用来出发懒加载的算子
  mapPartitionsWithIndex.count()

  /*
      运算结果:
                分区为 0 , 数据为 1=2
                分区为 1 , 数据为 5
                分区为 2 , 数据为 7=8=9
                分区为 3 , 数据为 1=2=3
   */


  /*
      val rdd: RDD[Int] = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3), 4)
      val sample = rdd.sample(true, 3)
      运算结果:
                分区为 1 , 数据为 4=4=4=4=5=5=5=6
                分区为 0 , 数据为 1=1=1=1=1=1=2=2=2=3=3=3=3=3
                分区为 2 , 数据为 7=7=7=7=8=8=9=9=9=9=9
                分区为 3 , 数据为 0=0=0=0=1=1=2=3=3=3=3=3=3=3
  */
  println("----------------sample结束------------------")
}

7.union(另外一个RDD)

  • 定义:两个RDD求一个并集返回一个新的RDD 两个RDD的类型必须保持一致
  • 分区:两个RDD的分区数之和
  • 案例:
def unionOper(sc: SparkContext): Unit = {
  println("----------------union开始------------------")
  val rdd = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8, 9), 3)
  val rdd1 = sc.makeRDD(Array(1, 12, 13, 14), 2)
  val rdd2 = rdd.union(rdd1)
  println("union后的分区数:" + rdd2.getNumPartitions) // union后的分区数:5
  rdd2.foreach((num: Int)=>print(num + ",")) // 4,1,5,2,6,3,7,8,9,1,12,13,14,
  println("----------------union结束------------------")
}

8. intersection(另外一个RDD) 交集 两个RDD类型一致

  • 分区:两个RDD的分区数中的最大值
  • 案例:
def intersectionOper(sc: SparkContext): Unit = {
  println("----------------intersection开始------------------")
  val rdd = sc.makeRDD(Array(1, 2, 3, 4, 5, 6, 7, 8, 9), 3)
  val rdd1 = sc.makeRDD(Array(1, 12, 13, 14), 2)
  val rdd2 = rdd.intersection(rdd1)
  println("intersection交集后的分区数:" + rdd2.getNumPartitions) // 交集后的分区数:3
  rdd2.foreach((num: Int)=>print(num + ",")) // 1,
  println("----------------intersection结束------------------")
}

9.distinct(numPartitions=默认值) 对rdd进行去重

  • 分区:分区数不变
  • 案例:
def distinctOper(sc: SparkContext): Unit = {
  println("----------------distinct开始------------------")
  val rdd = sc.makeRDD(Array(1, 1, 1, 1, 5, 6, 7, 8, 9), 3)
  val rdd2 = rdd.distinct()
  println("去重后的分区数:" + rdd2.getNumPartitions) // 去重后的分区数:3
  rdd2.foreach(println(_)) // 1 5 6 7 8 9
  println("----------------distinct结束------------------")
}

10.repartition(numPartitios) 对RDD数据集指定的分区数重新分区

  • 案例:
def repartitionOper(sc: SparkContext): Unit = {
  println("----------------repartition开始------------------")
  val rdd = sc.makeRDD(Array(1, 1, 1, 1, 5, 6, 7, 8, 9), 10)
  println(rdd.getNumPartitions) // 10
  val rdd2 = rdd.repartition(2)
  println(rdd2.getNumPartitions) // 2
  println("----------------repartition结束------------------")
}
posted @ 2022-08-23 19:47  jsqup  阅读(23)  评论(0编辑  收藏  举报