Spark学习之路(三)【RDD编程 API——转换算子Transformation】

RDD编程API

Spark支持两个类型(算子)操作:TransformationAction

Transformation

主要做的是就是将一个已有的RDD生成另外一个RDD。Transformation具有lazy特性(延迟加载)。Transformation算子的代码不会真正被执行。只有当我们的程序里面遇到一个action算子的时候,代码才会真正的被执行。这种设计让Spark更加有效率地运行。

常用的Transformation
转换含义
map(func)返回一个新的RDD,该RDD由每一个输入元素经过func函数转换后组成
filter(func)返回一个新的RDD,该RDD由经过func函数计算后返回值为true的输入元素组成
flatMap(func)类似于map,但是每一个输入元素可以被映射为0或多个输出元素(所以func应该返回一个序列,而不是单一元素)
mapPartitions(func)类似于map,但独立地在RDD的每一个分片上运行,因此在类型为T的RDD上运行时,func的函数类型必须是Iterator[T] => Iterator[U]
mapPartitionsWithIndex(func)类似于mapPartitions,但func带有一个整数参数表示分片的索引值,因此在类型为T的RDD上运行时,func的函数类型必须是(Int, Interator[T]) => Iterator[U]
sample(withReplacement, fraction, seed)根据fraction指定的比例对数据进行采样,可以选择是否使用随机数进行替换,seed用于指定随机数生成器种子
union(otherDataset)对源RDD和参数RDD求并集后返回一个新的RDD
intersection(otherDataset)对源RDD和参数RDD求交集后返回一个新的RDD
distinct([numTasks]))对源RDD进行去重后返回一个新的RDD
groupByKey([numTasks])在一个(K,V)的RDD上调用,返回一个(K, Iterator[V])的RDD
reduceByKey(func, [numTasks])在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,使用指定的reduce函数,将相同key的值聚合到一起,与groupByKey类似,reduce任务的个数可以通过第二个可选的参数来设置
aggregateByKey(zeroValue)(seqOp, combOp, [numTasks])先按分区聚合 再总的聚合 每次要跟初始值交流 例如:aggregateByKey(0)(+,+) 对k/y的RDD进行操作
sortByKey([ascending], [numTasks])在一个(K,V)的RDD上调用,K必须实现Ordered接口,返回一个按照key进行排序的(K,V)的RDD
sortBy(func,[ascending], [numTasks])与sortByKey类似,但是更灵活 第一个参数是根据什么排序 第二个是怎么排序 false倒序 第三个排序后分区数 默认与原RDD一样
join(otherDataset, [numTasks])在类型为(K,V)和(K,W)的RDD上调用,返回一个相同key对应的所有元素对在一起的(K,(V,W))的RDD 相当于内连接(求交集)
cogroup(otherDataset, [numTasks])在类型为(K,V)和(K,W)的RDD上调用,返回一个(K,(Iterable,Iterable))类型的RDD
cartesian(otherDataset)两个RDD的笛卡尔积 的成很多个K/V
pipe(command, [envVars])调用外部程序
coalesce(numPartitions**)**重新分区 第一个参数是要分多少区,第二个参数是否shuffle 默认false 少分区变多分区 true 多分区变少分区 false
repartition(numPartitions)重新分区 必须shuffle 参数是要分多少区 少变多
repartitionAndSortWithinPartitions(partitioner)重新分区+排序 比先分区再排序效率高 对K/V的RDD进行操作
foldByKey(zeroValue)(seqOp) (无)该函数用于K/V做折叠,合并处理 ,与aggregate类似 第一个括号的参数应用于每个V值 第二括号函数是聚合例如:+
combineByKey合并相同的key的值 rdd1.combineByKey(x => x, (a: Int, b: Int) => a + b, (m: Int, n: Int) => m + n)
partitionBy(partitioner)对RDD进行分区 partitioner是分区器 例如new HashPartition(2
cacheRDD缓存,可以避免重复计算从而减少时间,区别:cache内部调用了persist算子,cache默认就一个缓存级别MEMORY-ONLY ,而persist则可以选择缓存级别
persist
Subtract返回前rdd元素不在后rdd的rdd
leftOuterJoin (无)leftOuterJoin类似于SQL中的左外关联left outer join,返回结果以前面的RDD为主,关联不上的记录为空。只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可。
rightOuterJoin (无)rightOuterJoin类似于SQL中的有外关联right outer join,返回结果以参数中的RDD为主,关联不上的记录为空。只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可
subtractByKey (无)substractByKey和基本转换操作中的subtract类似只不过这里是针对K的,返回在主RDD中出现,并且不在otherRDD中出现的元素
Transformation测试代码
package com.baizhi

import org.apache.spark.storage.StorageLevel
import org.apache.spark.{Partitioner, SparkConf, SparkContext}

import scala.collection.mutable

object TransformationsDemo2 {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[*]").setAppName("transformations demo")
    val sc = new SparkContext(conf)
    // ======================flatMap===============================================
    // val rdd = sc.parallelize(List("Hello World","Hello Spark"),2)
    // 类似于map,但是每一个输入元素可以被映射为0或多个输出元素
    // rdd.flatMap(_.split(" ")).foreach(println)


    // ======================mapPartitions===============================================
    // val rdd = sc.parallelize(1 to 10,2)
    // rdd.mapPartitions(mpFunction).collect
    // def mpFunction(iter: Iterator[Int]): Iterator[Int] = {
    //   val list = List[Int]()
    //   println(iter.mkString(","))
    //   list.iterator
    // }

    // ======================mapPartitionsWithIndex===============================================
    // val rdd = sc.parallelize(1 to 10,3)
    // rdd.mapPartitionsWithIndex(mpFunction2).collect
    // def mpFunction2(index:Int,iter: Iterator[Int]):Iterator[Int] = {
    //   println("index:"+index)
    //   println(iter.mkString(","))
    //   iter
    // }

    // =======================sample==============================================
    // 数据抽样
    // val rdd = sc.parallelize(1 to 10,3)
    // 元素不可以多次抽样:withReplacement=false,每个元素被抽取到的概率为0.5
    // rdd.sample(false,0.5).collect.foreach(println)
    // 元素可以多次抽样:withReplacement=true,每个元素被抽取到的期望次数为2
    // rdd.sample(true,1.5).collect.foreach(println)

    // =======================union==============================================
    // val rdd = sc.parallelize(1 to 5,2)
    // val rdd2 = sc.parallelize(3 to 8,2)
    // 求并集
    // rdd.union(rdd2).collect.foreach(println)

    // 求交集
    // 1 2 3 4 5
    //     3 4 5 6 7 8
    // result:3 4 5
    // rdd.intersection(rdd2).collect.foreach(println)

    // =======================distinct==============================================
    // 去重
    // val rdd = sc.parallelize(List[Int](1,2,2,3,3,4,5),2)
    // rdd.distinct(2).collect.foreach(println)

    // =======================groupByKey==============================================
    // val rdd = sc.parallelize(List("Hello World","Hello Spark"),2)
    // rdd.flatMap(_.split(" ")).map((_,1)).groupByKey.collect().foreach(println)
    // result: (Hello,CompactBuffer(1, 1))
    //         (World,CompactBuffer(1))

    // =======================reduceByKey==============================================
    // val rdd = sc.parallelize(List("Hello World", "Hello Spark"), 2)
    // rdd.flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _).collect.foreach(println)
    // result: (Hello,2)
    //         (World,1)

    // =======================aggregateByKey==============================================
    // def seqFunc(a: Int, b: Int): Int = {
    //  Math.max(a, b)
    // }
    // def combFunc(a: Int, b: Int): Int = {
    //  a + b
    // }
    // val rdd = sc.parallelize(List("Hello World", "Hello Spark"), 2)
    // rdd.flatMap(_.split(" ")).map((_, 1)).aggregateByKey(10)(seqFunc,combFunc).collect.foreach(println)

    // val rdd = sc.parallelize(List(("user1","www.baidu.com"),("user2","www.taobao.com"),("user1","www.sina.com")),2)
    // val set = mutable.Set[String]()
    // rdd.aggregateByKey(set)((set,v) => set += v,(e1,e2) => e1 ++= e2).collect.foreach(println)
    // result: (user1,Set(www.sina.com, www.baidu.com))
    //         (user2,Set(www.taobao.com))

    // =======================sortByKey==============================================
    // val rdd = sc.parallelize(List("Hello World", "Hello Spark"), 2)
    // rdd.flatMap(_.split(" ")).map((_, 1)).sortByKey(false).collect.foreach(println)

    // =======================sortBy==============================================
    // val rdd = sc.parallelize(List("Hello World","Hello Spark"),2)
    // rdd.flatMap(_.split(" ")).map((_,1)).sortBy(_._1,false).collect.foreach(println)

    // =======================join==============================================
    // 类似于内连接
    // val rdd1 = sc.parallelize(List(("k1",1),("k2",2)),2)
    // val rdd2 = sc.parallelize(List(("k1","v1"),("k2","v2"),("k3","v3")),2)
    // rdd1.join(rdd2).collect.foreach(println)
    // result: (k1,(1,v1))
    //         (k2,(2,v2))

    // =======================cogroup==============================================
    // val rdd1 = sc.parallelize(List(("k1", 1), ("k2", 2)), 2)
    // val rdd2 = sc.parallelize(List(("k1", "v1"), ("k2", "v2"), ("k3", "v3")), 2)
    // rdd1.cogroup(rdd2).collect.foreach(println)
    // result: (k3,(CompactBuffer(),CompactBuffer(v3)))
    //          (k1,(CompactBuffer(1),CompactBuffer(v1)))
    //          (k2,(CompactBuffer(2),CompactBuffer(v2)))

    // =======================cartesian==============================================
    // 笛卡尔积
    // val rdd1 = sc.parallelize(List(("k1", 1), ("k2", 2)), 2)
    // val rdd2 = sc.parallelize(List(("k1", "v1"), ("k2", "v2"), ("k3", "v3")), 2)
    // rdd1.cartesian(rdd2).collect().foreach(println)
    // result: ((k1,1),(k1,v1))
    //          ((k1,1),(k2,v2))
    //          ((k1,1),(k3,v3))
    //          ((k2,2),(k1,v1))
    //          ((k2,2),(k2,v2))
    //          ((k2,2),(k3,v3))

    // =======================pipe==============================================
    // val rdd = sc.parallelize(List("hi", "hello", "how", "are", "you"),2)
    // rdd.pipe("/Users/gaozhy/echo.sh").collect.foreach(println)

    // =======================coalesce==============================================
    // 合并分区
    // val rdd = sc.parallelize(1 to 10,2)
    // rdd.coalesce(1).collect.foreach(println)

    // =======================repartition==============================================
    // 重新分区
    // val rdd = sc.parallelize(1 to 10,2)
    // rdd.mapPartitionsWithIndex((index,iter) => {
    //   println(index +" ---> "+iter.mkString(","))
    //  iter
    // }).collect
    // println("-----------------")
    // val newRDD = rdd.repartition(4)
    // newRDD.mapPartitionsWithIndex((index,iter) => {
    //   println(index +" ---> "+iter.mkString(","))
    //   iter
    // }).collect

    // =======================repartitionAndSortWithinPartitions==============================================
    // val rdd = sc.parallelize(List(("k1","v1"),("k3","v3"),("k2","v2")),2)
    // rdd.repartitionAndSortWithinPartitions(new CustomPartitioner).collect.foreach(println)
    // result: (k1,v1)
    //         (k2,v2)
    //         (k3,v3)

    // =======================combineByKey==============================================
    // val rdd = sc.parallelize(List(("k2",2),("k1",1),("k3",3),("k2",2)),2)
    // rdd.combineByKey(x => x, (a: Int, b: Int) => a + b, (m: Int, n: Int) => m + n).collect().foreach(println)

    // =======================partitionBy==============================================
    // val rdd = sc.parallelize(List(("k2",2),("k1",1),("k3",3),("k2",2)),2)
    // rdd.partitionBy(new CustomPartitioner).collect()


    // =======================cache==============================================
    // rdd缓存
    // val rdd = sc.parallelize(List(("k2",2),("k1",1),("k3",3),("k2",2)),2)
    // rdd.cache()

    // =======================persist==============================================
    // val rdd = sc.parallelize(List(("k2",2),("k1",1),("k3",3),("k2",2)),2)
    // rdd.persist(StorageLevel.DISK_ONLY).collect().foreach(println)

    // =======================Subtract==============================================
    // 返回第一个rdd中在第二个rdd不存在的值
    // val rdd1 = sc.parallelize(1 to 5,2)
    // val rdd2 = sc.parallelize(3 to 8,2)
    // rdd1.subtract(rdd2).collect().foreach(println)

    // foldByKey(无)
    // leftOuterJoin(无)
    // rightOuterJoin(无)
    // rightOuterJoin(无)
  }

  class CustomPartitioner extends Partitioner{
    override def numPartitions: Int = 1

    override def getPartition(key: Any): Int = (key.hashCode() & Integer.MAX_VALUE) % numPartitions
  }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值