RDD类操作说明

25 篇文章 0 订阅
1.RDD类由SparkContext进行创建。
2.我们总是说RDD是lazy的,并不是说RDD类中定义了lazy的方法,RDD对应的数据是存在BlockStore的子类中的,说RDD是lazy的,意思是RDD在调用BlockStore,使用数据的时候,BlockStore中,初始化数据块的操作是lazy的.

RDD基本转换操作(Transformation)
map[U:ClassTag](f:T=>U):RDD[U]map函数将RDD中类型为T的元素,一对一的转化成类型为U的元素。
distinct():RDD[T]distinct函数返回RDD中所有不一样的元素
flatMap[U:ClassTag](f:T=>TraversableOnce[U]):RDD[U]flatMap函数则是将RDD中的每一个元素进行一对多的转换。
repartition(numPartition:Int):RDD[T]
coalesce(numPartition:Int,shuffle:Boolean=false):RDD[T]
对RDD进行重新分区
randomSplit(weight:Array[Double],seed:Long=System.nanoTime):Array[RDD[T]]根据weight权重将一个RDD切分成多个RDD
glom()将RDD中每一个分区中类型为T的元素转换成数组Array[T],这样每一个分区就只有一个数组元素
union(other:RDD[T]):RDD[T]并集
intersection(other:RDD[T]):RDD[T]交集
subtract(other:RDD[T]):RDD[T]差集
mapPartitions[U:ClassTag](f:Iterator[T]=>Iterator[U],preservesPartitioning:Boolean=False):RDD[U]
mapPartitionsWithIndex[U:ClassTag](f:(Int,Iterator[T])=>Iterator[U],preservesPartitioning:Boolean=False):RDD[U]
这两个函数的作用和map差不多,但是如果在映射过程中需要频繁的创建额外的对象,那么map函数的效率就不是很高了,这时使用mapPartitions和mapPartitionsWithIndex效果会比较好
zip[U:ClassTag](other:RDD[U]):RDD[(T,U)]
zipPartitions[B:ClassTag,V;ClassTag](rdd2:RDD[B],preservesPartitioning)(f:(Iterator[T],Iterator[B])=>Iterator[V]):RDD[V]
....
zip用来将两个RDD组合成Key/Value形式的RDD,这里默认分区个数和元素数量相同。
zipPartitions是将多个RDD按照partition组合成新的RDD,需要组合的RDD具有相同的分区数。
例子:
val rdd = sc.makeRDD(1 to 5, 2)
val rdd1 = sc.makeRDD(Array("1","2","3", "4", "5","6"),2)
val zipPartitionsRDD=rdd.zipPartitions(rdd1)((i:Iterator[Int],Iterator[String])=>{Iterator(i.toArrray.size,s.to.Array.size)})
zipPartitionsRDD.collect()
输出:
Array(2,3,3,3)
zipWithIndex():RDD[(T,Long)]
zipWithUniqueId():RDD[(T,Long)]
将RDD中的元素和这个元素的ID组成键/值对,zipWithIndex和zipWithUniqueId有一个主要的区别,zipWithIndex需要启动一个Spark作业来计算每一个分区的开始索引号,一边能顺序索引。而zipWithUniqueId不需要这样一个额外作业。
索引号从0开始。
sample(withReplacement,frac,seed)(作用待定)根据给定的随机种子seed,随机抽样出数量为frac的数据。是否在样本中重复抽取由withReplacement决定。
pipe(command,[envVars])通过管道的方式对RDD的每个分区使用shell命令进行操作,返回相应的结果
groupBy
可以指定分组的列
  

键值RDD转换操作(Transformation):RDD[(K,V)]
这些方法主要使用到隐式转换PairRDDFunctions
partitionBy(p:Partitioner):RDD[(K,V)]
根据p函数生成新的ShuffledRDD,将原RDD重新分区,输入的参数使用到Partitioner的子类,HashPartitioner和RangePartitioner
mapValue[U](f:V=>U):RDD[(K,U)]针对V进行map操作
flatMapValues[U](f:V=>TraversableOnce[U]):RDD[(K,U)]针对V进行flatMap操作
combineByKey
foldByKey
reduceByKey
groupBykey
这四种键值对转换操作都是针对RDD[K,V]本身,不涉及与其他RDD的组合操作,四种操作最终都会归结为对combineByKey的调用。将RDD[K,V]转化为RDD[K,C]。
例子:
val pairs=sc.parallelize(Array((1,1),(1,2),(1,3),(2,1),(1,1)))
val bufs= pairs.mapValues(v=>HashSet(v))
val sums=bufs.foldByKey(new HashSet[Int])(_++=_)
//以下输出Array((2,Set(1)),(1,Set(1,2,3)))
sums.collect()
val reduceByKeyRDD=pairs.reduceByKey(_+_)
//以下输出Array((2,1),(1,7))
reduceByKeyRDD.collect()
val groupByKeyRDD=pairs.groupByKey()
//以下输出Array((2,ArrayBuffer(1)),(1,ArrayBuffer(1,2,3,1)))
groupByKeyRDD.collect()
cogroup
join
leftOuterJoin
rightOuterJoin
subtractByKey
针对RDD[K,V]中的K值进行相等连接操作,都是调用cogroup来实现,很容易用。打几个例子看以下就知道了。
例子:
val rdd1=sc.parallelize(Array((1,1),(1,2),(2,1),(3,1)),1)
val rdd2=sc.parallelize(Array((1,'x'),(2,'y'),(2,'z'),(4,'w')),1)
val cogroupRDD=rdd1.cogroup(rdd2)//外链接
val joinRDD=rdd1.join(rdd2)
val leftOuterJoinRDD=rdd1.leftOuterJoin(rdd2)
val rightOuterJoinRDD=rdd1.rightOuterJoin(rdd2)
val subtractByKeyRDD=rdd1.subtractByKey(rdd2)
sortByKey根据值排序
cartesian(otherDataset)
笛卡尔积。在数据集T和U上调用时,返回一个(T,U)对。

这个函数不当当会把集合T和U合起来,连两则在hdfs中执行的task数都会乘起来,例如T有20个task,U有20个task,那么使用cartesian后,会有400个task在运行

控制操作
cache():RDD[T]在action后,将RDD对应的Data存放在内存中
persist():RDD[T]同上
persist(level:StorageLevel):RDD[T]
这个persist可以设置RDD在action之后存放的级别(内存,磁盘。。。)
checkpoint()
checkpoint接口是将RDD持久化在HDFS中,其与persist的一个区别是checkpoint将会切断此RDD之前的依赖关系,而persist接口依然保留着RDD的依赖关系.在checkpoint之前要用sc.setCheckpointDir(path),设置checkpoint后RDD的持久化地址。checkpoint比persist更安全

行动操作(Action)
first返回RDD中的第一个元素
count返回RDD中元素的个数
reduce(f:(T,T)=>T)对RDD中的元素进行二元计算,返回计算结果
collect()/toArray()以集合的形式返回RDD的元素
take(num:Int)(作用待定)将RDD作为集合,返回集合中[0,num-1]下标的元素
top(num:Int)按照默认的或者是指定的排序规则,返回前num个元素
takeOrdered(num:Int)以与top相反的排序规则,返回前num个元素
aggregate[U](zeroValue:U)(seqOp:(U,T)=>U,combOp(U,U)=>U)aggregate行动操作中主要提供两个函数,一个是seqOp函数,将RDD中的每一个分区的数据聚合成类型为U的值。另一个函数combOp将各个分区聚合起来的值合并在一起得到最终类型为U的返回值。
fold(zeroValue:T)(op:(T,T)=>T)fold是aggregate的便利接口,其中op操作及时seqOp也是combOp操作。
lookup(key:K):Seq[V]针对(K,V)类型RDD的行动操作,对于给定的键值,返回与此键值相对应的所有值。
takeSample(withReplacement,frac,seed )
saveAsTextFile(path)
saveAsSequenceFile(path)
saveAsObjectFile(path)使用java的系列化方法保存到本地文件,可以被SparkContext.objectFile()加载
countByKey()对(K,V)l类型的RDD有效
foreach(func)
在数据集上的每一个元素上,运算函数func,通常用于一个更新累加器变量或者和外部存储系统进行交互.
foreach操作有一个问题,在foreach中改变全局变量的值,不能在foreach外观察得到,
例如:
val testrdd = sc.parallelize(1 to 4)
var a = 0
//以下操作过后,a的值还是0
testrdd.foreach(x=>a+=x)
//只有通过以下操作才可以改变a的值
testrdd.collect.foreach(x=>a+=x)
collect()查看当前转换结果
collectPartitions()查看每个分区中的结果
  

其他操作
getStorageLevel()
获取当前RDD的存储级别
getDependencies 
getPartitions 



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值