Spark算子

Spark有许多常用算子,这里结合几篇文章做一下备份,方便自己后面快速查阅。本篇文章主要分析每个算子的应用方法,后面写到RDD、DataSet和DataFrame区别的时候会从算子的数据类型转变的进行进一步分析。

Transformation

  • map
    map的输入变换应用于RDD中的所有元素。
scala> val array = Array(1,2,3,4)
array:Array[Int] = Array(1, 2, 3, 4)
scala>array.map(x=>(x,"spark"))
res0:Array[(Int,String)]=Array((1,"spark"),(2,"spark"),(3,"spark"),(4,"spark"))
  • flatmap
    flatmap与map的区别在于flat,flat有扁平的意思。
scala> val arr = Array("spark,datas","hadoop,datah","python,datap")
arr:Array[String] = Array(spark,datas,hadoop,datah,python,datap)
scala> arr.flatmap(x=>x.split(","))
res:Array[String] = Array(spark,datas,hadoop,datah,python,datap)
  • mapValues
scala> val list = List("hadoop","spark","hive","spark")
scala> val rdd = sc.parallelize(list)
scala> val pairRdd = rdd.map(x => (x,1))
scala> pairRdd.mapValues(_+1).collect.foreach(println)
res1:(hadoop,2),(spark,2),(hive,2),(spark,2)
  • mapPartitions
    mapPartitions与map的区别也在于partitions(分区),map每处理一个元素就需要调用一次函数,而mapPartition则是每个分区调用一次。有很多博客说在数据量很低的时候可以有效提升性能,有的也说用这个算子比较危险容易出现OOM问题。特别是对于一些容易产生数据激增的业务场景里面。但是对于一些写数据库的场景中具有很好的性能优化。因为对于分布式场景中,连接数据库的操作必须在算子内部才能被executor执行,这个时候每个partition只需要建立一次连接就好了。至于数据量上的区别还有待于我自己测试后进行说明!
  • filter(func)
    过滤操作,根据func的条件过滤RDD中元素。返回一个新的RDD
scala> val a = Array(1,2,3,4,5,6,7)
a:Array[Int] = Array(1, 2, 3, 4, 5, 6, 7)
scala> a.filter(x=>x%2 == 0)
res8:Array[Int] = Array(2,4,6,8)
  • union(rdd)
    合并两个数据集,不去重!!!
scala> val aa = Array(1,2,3)
aa: Array[Int] = Array(1, 2, 3)
scala> val bb = Array(3,4,5)
bb:Array[Int] = Array(3, 4, 5)
scala> aa.union(bb)
res:Array[Int] = Array(1,2,3,3,4,5)
  • instersect
    两个数据集求交集,并去重
scala> val aa = Array(1,2,3)
aa: Array[Int] = Array(1, 2, 3)
scala> val bb = Array(3,4,5)
bb:Array[Int] = Array(3, 4, 5)
scala> aa.instersect(bb)
res:Array[Int] = Array(3)
  • sample(withReplacement,fraction,seed)
    对数据集采样,withReplacement:表示是否放回采样;fraction:采样比例;seed:随机数种子
  • groupByKey([numTasks])
    pairRDD或(k,v)调用。返回一个(k,Iterable)。主要作用是将相同的key的值分配到一个集合序列中,当然顺序不一定。但是,需要将键值加载到内存中,如果一个键对应的值过多可能会出现OOM问题。先看例子:
# 计算单词的个数
scala> val words = Array("one","two","two","three","three","three")
scala> val wordPairRDD = sc.parallelize(words).map(word => (word, 1))
res:Array[(String,Int)] =  Array[(one,1),(two,1),(two,1),(three,1),(three,1),(three,1)]
scala> val wordGroup = wordPairRDD.groupByKey()
groupPair:RDD[(String,Iterable[Int])] = ShuffledRDD[4] at groupByKey
scala>val a =  wordGroup.collect()
res:Array[(String,Interable[Int])] = Array[("one",CompactBuffer(1)),
("two",CompactBuffer(1,1)),("three",CompactBuffer(1,1,1))]
# 这里访问方式注意一下,key是一组,value是一组。每一组里面可能也有多个元素。所以会有
#  先确定组再内部访问的方法!!!
scala>a.map(t=>(t._1,t._2.sum)).collect()

这里在补充一个例子,一般在工程中都是这样使用的。
注:1、groupBy(function)——>与groupByKey的区别在于,groupByKey是无参数的所以调用的结构本来就是key-value结构的。而groupBy中根据传入的函数来进行分组。举例来说:

scala> val a = List(("a",2),("a",3),("d",333),("c",3),("c",4))
scala> val b = a.groupBy(_._1)
b: scala.collection.immutable.Map[String,List[(String, Int)]] = 
Map(d -> List((d,333)), a -> List((a,2), (a,3)), c -> List((c,3), (c,4)))
scala> val c = b.mapValues(r => {r.map(r => {r._2})})
scala> println(c)
c: scala.collection.immutable.Map[String,List[Int]] = Map(d -> List(333), a -> List(2, 3), c -> List(3, 4))
  • reduceByKey
    reduceByKey的作用是聚合,groupByKey的作用是分组。上文例子中也可以使用reduceByKey来解决。解决方案如下所示:
val wordCount = wordPairsRDD.reduceByKey(_ + _).collect()

这个是根据key,对迭代器中的数值进行迭代累加。


  • 迭代器(Iterator)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值