一、Transformations算子

1.map-一对一

特点就是一对一,进来一个,出去一个

lines.map(one=>{
      one+"#"
    }).foreach(println)

2.flatMap-一对多

进来一个,出去一堆。比如读取一行数据:hello world ,出去的就是hello和world两个单词。匿名函数定义了其中的逻辑:将读取到的数据按照空格切分,最终输出多个单词

lines.flatMap(one=>{
      one.split(" ")
    }).foreach(println)

3.filter过滤

进来一个,只要符合定义规则的才能顺利输出出去。即:只有hello才能输出,其他单词全都被过滤掉

//先得到一堆单词
val rdd1 = lines.flatMap(one => {
      one.split(" ")
    })
    //定义过滤规则,进行过滤输出
    rdd1.filter(one=>{
      "hello".equals(one)
    }).foreach(println)

4.reduceByKey和sortBy

reduceByKey就是相当于MR的Reduce过程,将相同的key进行聚合,并执行对应的逻辑(这里是做+1,即统计单词个数)。
聚合后要对RDD进行排序了,这里是借助tuple二元组来做计数、排序的。按照tuple的第二位来进行排序,默认升序。如果想要降序,那就result.sortBy(tp=>{tp._2},false)

//得到split切割后的N多个单词
	val words = lines.flatMap(one => {one.split(" ")})
	//map,1 To 1,hello--->(hello,1)
    val pairWords = words.map(one=>{(one,1)})
    //聚合
    val result = pairWords.reduceByKey((v1:Int,v2:Int)=>{v1+v2})
    result.sortBy(tp=>{tp._2})//按照第二位来排序,进来tp,得到第二位
//    result.sortBy(tp=>{tp._2},false)//降序输出,默认升序
    result.foreach(println)

5.sortByKey

使用sortByKey实现sortBy的功能:“hello world”—>“hello” “world”—>(hello,1) (world,1)
关键的时候来了,利用tuple的swap反转,(hello 1)—>(1,hello)
使用sortByKey来进行排序,然后再利用一次反转

val words = lines.flatMap(one => {one.split(" ")})
    val pairWords = words.map(one=>{(one,1)})
    val result:RDD[(String,Int)] = pairWords.reduceByKey((v1:Int,v2:Int)=>{v1+v2})
    val transRDD = result.map(tp=>{tp.swap})//反转,string,int  变  int,string
    val r = transRDD.sortByKey(false)
    r.map(_.swap).foreach(println)

6.sample抽样

/**
     * sample算子抽样
     * true:抽出来一个,完事再放回去,再继续抽。
     * 0.1:抽样的比例
     * 100L:指定种子,抽到的数据不管运行多少次都一样
     */
    val result: RDD[String] = lines.sample(true,0.1,100L)
    result.foreach(println)

7.join

(k,v) (k,w)—>(k,(v,w)),k相同的join在一起

val result = rdd1.join(rdd2)

7.1 leftOuterJoin

以左为主,没有的就用None占坑

val result = rdd1.leftOuterJoin(rdd2)

7.2 rightOuterJoin

以右为主,没有的就用None占位

val result = rdd1.rightOuterJoin(rdd2)

8.union

合并两个数据集,类型要一致

val result = rdd1.union(rdd2)

9.intersection

取2个RDD的交集

val result = rdd1.intersection(rdd2)

10.subtract

取差集

val result = rdd1.subtract(rdd2)

11.mapPartitions

和map类似,遍历的单位是每个partition上的数据

val result = rdd1.mapPartitions(iter=>{
      val listBuffer = new ListBuffer[String]()
      println("打开")
      while (iter.hasNext){
        val s = iter.next()
        println("插入。。。"+s)
        listBuffer.append(s+"#")
      }
      println("关闭")
      listBuffer.iterator
    })

12.distinct:map+redeceByKey+map

相当于去重了

val rdd1: RDD[String] = sc.makeRDD(Array[String]("a", "b", "c", "a", "d", "e", "a", "b"))
    val result = rdd1.distinct()
    //等价
    val result = rdd1.map(s=>{(s,1)}).reduceByKey(_+_).map(tp=>tp._1)

13.cogroup

(K,V).cogroup(K,V)=>(K,([V],[W]))
输出:(zhangsan,(CompactBuffer(1),CompactBuffer(100)))

val result = nameRDD.cogroup(scoreRDD)
    result.foreach(println)

14.mapPartitionsWithIndex

index:分区号;
iter:分区号下的数据

val rdd2 = rdd1.mapPartitionsWithIndex((index, iter) => {
      val list = new ListBuffer[String]()
      while (iter.hasNext) {
        val one = iter.next()
        list += (s"rdd1 partition = $index ,value = $one")
      }
      list.iterator
    })
    rdd2.foreach(println)//rdd1 partition = 1 ,value = b

15.repartition

可以增多、减少分区。宽依赖算子,会产生shuffle;
这里区别于coalesce,coalesce同样可能增加、减少分区。但是coalesce是窄依赖算子,默认无shuffle,可通过设置true来开启。当coalesce由少的分区分到多的分区时,不让产生shuffle,不起作用。
因此可以变相的理解为:repartition常用于增多分区,coalesce常用于减少分区

val rdd3 = rdd2.repartition(3)
    rdd3.mapPartitionsWithIndex((index, iter) => {
      val list = new ListBuffer[String]()
      while (iter.hasNext) {
        val one = iter.next()
        list += (s"rdd1 partition = $index ,value = $one")
      }
      list.iterator
    }).foreach(println)

16.zip & zipwithindex

zip:两个RDD可以通过zip压缩在一起,输出结果:(a,1)

zipwithindex:Long就是RDD的index下标0,1,2…和各自的下标压缩在一起,形成K-V格式RDD。如:(a,0)

rdd1.zip(rdd2).foreach(println)
    val rdd: RDD[(String, Long)] = rdd1.zipWithIndex()
    rdd.foreach(println)

二、Action算子

1.count

//count:计算数据源有多少行
    val l = lines.count()
    println(l)

2.collect

回收计算结果到Driver端的内存

val strings: Array[String] = lines.collect()
    strings.foreach(println)

3.firs

拿到第一条数据。first就是由take(1)实现的

val result = lines.first()
    println(result)

4.tak

拿到指定行数的数据

val result = lines.take(5)
    result.foreach(println)

5.foreachPartition

遍历的是每个partition上的数据

rdd1.foreachPartition(iter=>{
      println("创建数据库连接")
      while (iter.hasNext){
        val s = iter.next()
        println("插入数据库:"+s)
      }
      println("关闭数据库连接")
    })

6.reduce &countByKey & countByValue

聚合执行对应逻辑,输出15

val reslut = sc.parallelize(List[Int](1,2,3,4,5)).reduce((v1,v2)=>{v1+v2})
    println(reslut)

countByKey按照key分组,count整体相同的有几个

sc.parallelize(List[(String,Int)](("a",100),("b",200),("a",300),("d",400))).countByKey().foreach(println)

countByValue:整体作为value分组,计算出现次数。输出:((a,100),2)

sc.parallelize(List[(String,Int)](("a",100),("b",200),("a",300),("a",100))).countByValue().foreach(println)