RDD算子实践

一.map算子

作用:

返回一个新的RDD,该RDD由每一个输入元素经过func函数转换后组成。源码中 map 算子相当于初始化一个 RDD,新RDD 叫做 MappedRDD(this, sc.clean(f))。

实践:

创建一个1-5数组的RDD,将所有元素*2形成新的RDD

object RDD_Operator {
  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("StuScore")
    val sc = new SparkContext(conf)
    //map算子
    var listRDD: RDD[Int] = sc.makeRDD(1 to 5)
    //var mapRDD : RDD[Int] = listRDD.map(x=>x*2)
    var mapRDD : RDD[Int] = listRDD.map(_*2)
    mapRDD.collect().foreach(println)
  }
}

实践:

创建一个string的集合的RDD,对所有元素加一个前缀"str_"

object RDD_Operator {
  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("StuScore")
    val sc = new SparkContext(conf)
    //map算子
    val array1 = List("spark","hadoop","hello")
    var listRDD: RDD[String] = sc.makeRDD(array1)
    var mapRDD : RDD[String] = listRDD.map("str_"+_)
    mapRDD.collect().foreach(println)
  }
}

二. mapPartitions算子

作用:

类似于map,可能会出现内存溢出,但效率优于map,减少了发送到执行器执行交互次数,而且独立地在RDD的每一个分区上运行,因此在类型为T的RDD上运行时,func的函数类型必须是Iterator[T] => Iterator[U]。假设有N个元素,有M个分区,那么map的函数的将被调用N次,而mapPartitions被调用M次,一个函数一次处理所有分区。在函数中通过这个分区整体的迭代器对整个分区的元素进行操作。

实践:

创建一个1-5数组的RDD,将所有元素*2形成新的RDD

//mapPartitions算子
    var listRDD1: RDD[Int] = sc.makeRDD(1 to 5)
    var mapPartitionsRDD: RDD[Int] = listRDD1.mapPartitions(datas=>{
      datas.map(data=>data*2)
    })
mapPartitionsRDD.collect().foreach(println)

三. mapPartitionsWithIndex算子

作用:

类似于mapPartitions,但func带有一个整数参数表示分片的索引值,因此在类型为T的RDD上运行时,func的函数类型必须是(Int, Interator[T]) => Iterator[U];

实践:

创建一个RDD,使每个元素跟所在分区形成一个元组组成一个新的RDD

//mapPartitionsWithIndex算子
    var listRDD1: RDD[Int] = sc.makeRDD(1 to 5,2) //makeRDD第二个参数是定义的分区数目
    val tupleRDD: RDD[(Int,String)] =listRDD1.mapPartitionsWithIndex{
      case(num,datas)=>{
        datas.map((_,"分区号,"+num)) //得到  每一条数据,"分区号",分区号
      }
    }

tupleRDD.collect().foreach(println)

四. flatMap算子

作用:

类似于map,但是每一个输入元素可以被映射为0或多个输出元素(所以func应该返回一个序列,而不是单一元素)

实践:

将集合拆成一个个元素

//flatMap算子
    var listRDD1: RDD[List[Int]] = sc.makeRDD(Array(List(1,2),List(3,4))) 
    var flatMapRDD: RDD[Int] = listRDD1.flatMap(datas=>datas)
flatMapRDD.collect().foreach(println)

五. glom算子

作用:

将每一个分区形成一个数组,形成新的RDD类型时RDD[Array[T]]

实践:

创建一个3个分区的RDD,并将每个分区的数据放到一个数组

//glom算子
    var listRDD1: RDD[Int] = sc.makeRDD(List(1,2,3,4,5,6,7,8),3)
    var glomRDD: RDD[Array[Int]] =listRDD1.glom()

    glomRDD.collect().foreach(array=>{
      println(array.mkString(","))
})

六. groupBy算子

作用:

分组,按照传入函数的返回值进行分组。将相同的key对应的值放入一个迭代器

实践:

创建一个RDD,按照元素模以2的值进行分组。

//groupBy算子
    var listRDD1: RDD[Int] = sc.makeRDD(List(1,2,3,4,5,6,7,8))
    //分组后的数据形成了对偶元组(K-V),k表示分组的key,v表示分组的数据集合,就是这里的[(Int,Iterable[Int])]
    var groupByRDD: RDD[(Int,Iterable[Int])] =listRDD1.groupBy(i=>i%2)

groupByRDD.collect().foreach(println)

七. filter算子

作用:

过滤。返回一个新的RDD,该RDD由经过func函数计算后返回值为true的输入元素组成。

实践:

需求:过滤出一个新RDD(元素值都为偶数)

//filter算子
    var listRDD1: RDD[Int] = sc.makeRDD(List(1,2,3,4,5,6,7,8))
    var filterRDD: RDD[Int] = listRDD1.filter(x=>x%2==0)

filterRDD.collect().foreach(println)

八. sortBy算子

作用:使用func先对数据进行处理,按照处理后的数据比较结果排序,默认为正序。

可对键值对数据进行value排序

案例:

//sortBy算子
    val rdd=sc.parallelize(List(("female",1),("male",5),("female",4),("male",2)))
    val reduce=rdd.sortBy(_._2,false).collect.foreach(println)

全排序

 先对第一个元素进行比较,若相同比较第二个元素,若一二个元素都相同比较第三个元素

//全排序  先对第一个元素进行比较,若相同比较第二个元素,若一二个元素都相同比较第三个元素
    val rdd1=sc.parallelize(List((2,1,10),(3,5,19),(3,5,1),(1,4,20),(3,2,24)))
    var r2=rdd1.collect.sorted.foreach(println)

案例:

创建一个RDD,按照3的余数进行排序

//sortBy算子
    var listRDD1: RDD[Int] = sc.makeRDD(List(5,8,1,6))
    var sortByRDD: RDD[Int] = listRDD1.sortBy(x=>x%3)  //按照3的余数排序
sortByRDD.collect().foreach(println)

九. partitionBy算子

作用:

对pairRDD进行分区操作,如果原有的partionRDD和现有的partionRDD是一致的话就不进行分区, 否则会生成ShuffleRDD,即会产生shuffle过程。

案例:

创建一个4个分区的RDD,对其重新分区为两个分区

//partitionBy算子
    val rdd = sc.parallelize(Array((1,"aaa"),(2,"bbb"),(3,"ccc"),(4,"ddd")),4)
    println("分区数:"+rdd.partitions.size)
    var rdd2 = rdd.partitionBy(new org.apache.spark.HashPartitioner(2))
println("分区数:"+rdd2.partitions.size)

十. groupByKey算子

作用:groupByKey也是对每个key进行操作,但只生成一个sequence。

案例:

创建一个pairRDD,将相同key对应值聚合到一个sequence中,并计算相同key对应值的相加结果。

//groupByKey算子
    val words=Array("one","two","three","three","three" )
    val wordPairRDD=sc.parallelize(words).map(word=>(word,1))
    val group=wordPairRDD.groupByKey()//将相同key对应值聚合到一个sequence中
    group.collect.foreach(println)//直接打印
group.map(t=>(t._1,t._2.sum)).collect.foreach(println)//聚合

 

 

十一. reduceByKey算子

作用:在一个(Key,Value)的RDD上调用,返回一个(Key,Value)的RDD,使用指定的reduce函数,将相同key的值聚合到一起,reduce任务的个数可以通过第二个可选的参数来设置。

案例:创建一个pairRDD,计算相同key对应值的相加结果

//reduceByKey算子
    val rdd=sc.parallelize(List(("female",1),("male",5),("female",5),("male",2)))
    val reduce=rdd.reduceByKey((x,y)=>x+y)
    reduce.collect.foreach(println)

 

posted @ 2020-04-20 01:15  saaas  阅读(140)  评论(0)    收藏  举报