Terry's blog

Focus on bigdata and cloud.

博客园 首页 新随笔 联系 订阅 管理

1. Spark RDD 创建操作

 1.1 数据集合

  parallelize 可以创建一个能够并行操作的RDD。其函数定义如下:

def parallelize[T: ClassTag](
seq: Seq[T],
numSlices: Int = defaultParallelism): RDD[T] = withScope {
assertNotStopped()
new ParallelCollectionRDD[T](this, seq, numSlices, Map[Int, Seq[String]]())
}

  由定义可见有两个参数,第一个参数指定数据集合,第二个参数指定数据分区。

实例:由普通数组创建RDD 

scala> val data=Array(1,2,3,4,5,6,7,8,9) 
data: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> val rdd=sc.parallelize(data,3)
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:26

1.2 外部数据源

    textFiles 可以通过Hadoop支持的外部数据源(包括本地文件系统、HDFS、Cassandra、HBase等)建立RDD。其定义如下:

def textFile(
path: String,
minPartitions: Int = defaultMinPartitions): RDD[String]

 第一个参数指定数据路径,第二个参数指定数据分区。

def defaultMinPartitions: Int = math.min(defaultParallelism, 2)

 scala> sc.defaultParallelism 

res0: Int = 2

由以上可知,如果第二个参数如果不设置默认为2,默认的并行度最大不超过2.

 实例1:读取本地文件创建RDD

scala> val rdd1=sc.textFile("file:///usr/local/doc/name1.txt")
rdd1: org.apache.spark.rdd.RDD[String] = file:///usr/local/doc/name1.txt MapPartitionsRDD[15] at textFile at <console>:24
scala> rdd1.collect
res7: Array[String] = Array(james, jack, jenny)

 实例2:读取hdfs上的文件创建RDD 

[root@master doc]# hdfs dfs -cat /1.txt
hello world
hello terry
hello james
hello curry
hello bill
hello kact
hello james 
scala> val rdd2=sc.textFile("hdfs://master:9000/1.txt")
rdd2: org.apache.spark.rdd.RDD[String] = hdfs://master:9000/1.txt MapPartitionsRDD[1] at textFile at <console>:24
scala> rdd2.collect
res0: Array[String] = Array(hello world, hello terry, hello james, hello curry, hello bill, hello kact, hello james) 

2. Spark RDD 转换操作

  2.1 map(func)

 对集合的每一个元素运用某个函数操作,然后将结果作为一个新的列表返回。 
 实例:将列表中每个元素值乘以2 
scala> val rdd1=sc.parallelize(1 to 6,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24
scala> val rdd2=rdd1.map(_*2)
rdd2: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[1] at map at <console>:25
scala> rdd2.collect
res0: Array[Int] = Array(2, 4, 6, 8, 10, 12) 

  2.2 filter(func)

 对RDD元素进行过滤,返回值为true的元素组成的一个新的数据集。

实例:返回数据集中的偶数

scala> val rdd1=sc.parallelize(1 to 9,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[4] at parallelize at <console>:24
scala> val rdd3=rdd1.filter(x=>x%2==0)
rdd3: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[5] at filter at <console>:25
scala> rdd3.collect
res3: Array[Int] = Array(2, 4, 6, 8)

2.3 flatMap(func)  

对集合中每个元素运用某个函数操作(每个元素会被映射为0到多个输出元素)后,将结果扁平化组成一个新的集合。 
实例2:每个元素映射为多个元素
 scala> val rdd1=sc.parallelize(1 to 3,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24
scala> val rdd4=rdd1.flatMap(x=>x to 5)
rdd4: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[1] at flatMap at <console>:25
scala> rdd4.collect
res0: Array[Int] = Array(1, 2, 3, 4, 5, 2, 3, 4, 5, 3, 4, 5)

2.4 mapPartitions(func)

 与map类似,map函数是应用到每个元素,而mapPartitions的输入函数是每个分区的数据,把每个分区中的内容作为整体来处理的。 当map里面有比较耗时的初始化操作时,比如连接db,可以采用mapPartitions,它对每个partition操作一次,其函数的输入与输出都是iterator类型。其定义如下:
def mapPartitions[U: ClassTag](
f: Iterator[T] => Iterator[U],
preservesPartitioning: Boolean = false): RDD[U]
 实例如下:
scala> val rdd1=sc.parallelize(1 to 9,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24
scala> def myfunc[T](iter:Iterator[T]):Iterator[(T,T)]={
     | var res=List[(T,T)]()
     | var pre=iter.next
     | while (iter.hasNext) {
     | val cur=iter.next
     | res.::=(pre,cur)
     | pre=cur
     | }
     | res.iterator
     | }
myfunc: [T](iter: Iterator[T])Iterator[(T, T)]
scala> rdd1.mapPartitions(myfunc)
res2: org.apache.spark.rdd.RDD[(Int, Int)] = MapPartitionsRDD[2] at mapPartitions at <console>:28
scala> res2.collect()
res3: Array[(Int, Int)] = Array((2,3), (1,2), (5,6), (4,5), (8,9), (7,8))  

 

2.5 mapPartitionsWithIndex(func)
与 mapPartitions 类似,其传入的函数除了数据集,还需一个分区的index.其定义如下:
private[spark] def mapPartitionsWithIndexInternal[U: ClassTag](
f: (Int, Iterator[T]) => Iterator[U],
preservesPartitioning: Boolean = false): RDD[U]
实例如下:
scala> val rdd1=sc.parallelize(1 to 9,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24 
scala> val mapReslut=rdd1.mapPartitionsWithIndex{
     | (index,iterator)=>{
     | val list=iterator.toList
     | list.map(x=>x +"->"+index).iterator
     | }
     | }
mapReslut: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[3] at mapPartitionsWithIndex at <console>:25
scala> mapReslut.collect
res6: Array[String] = Array(1->0, 2->0, 3->0, 4->1, 5->1, 6->1, 7->2, 8->2, 9->2) 

 2.6 sample(withReplacement, fraction, seed)

 根据给定的随机种子seed,随机抽样出数量为fraction的数据。其定义如下:
def sample(
withReplacement: Boolean,
fraction: Double,
seed: Long = Utils.random.nextLong): RDD[T]

 withReplacement取回的数据是否放回抽样,fraction:比例,0.1表示10%,seed:随机种子,相同的seed得到的随机序列一样。

 实例: 

scala> val rdd1=sc.parallelize(1 to 1000,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[2] at parallelize at <console>:24
scala> rdd1.sample(false,0.1,1).count
res1: Long = 116

 2.7 union(otherDataset)

  两个数据集合并,不去重,返回一个新的数据集,即所有旧的rdd的partition,直接移到新的rdd,新rdd 的Partition数量为旧rdd的partition数量的和。

 实例:

scala> val rdd1=sc.parallelize(1 to 6,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[4] at parallelize at <console>:24
scala> val rdd2=rdd1.map(_*2)
rdd2: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[5] at map at <console>:25
scala> val rdd3=rdd1.union(rdd2)
rdd3: org.apache.spark.rdd.RDD[Int] = UnionRDD[6] at union at <console>:27
scala> rdd3.collect
res2: Array[Int] = Array(1, 2, 3, 4, 5, 6, 2, 4, 6, 8, 10, 12)

 查看新rdd的partition数量

scala> rdd3.partitions.length 

res3: Int = 6

 2.8 intersection(otherDataset)

 数据交集,相交的数据组成一个新的数据集返回。

实例:

scala> val rdd4=rdd1.intersection(rdd2)
rdd4: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[12] at intersection at <console>:27
scala> rdd4.collect
res3: Array[Int] = Array(6, 4, 2)

2.9 distinct([numPartitions]))

去除两个数据集的重复数据,返回去重后的数据集。

 实例: 

scala> val rdd5=rdd1.union(rdd2).distinct 
rdd5: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[16] at distinct at <console>:27
scala> rdd5.collect
res4: Array[Int] = Array(6, 12, 1, 8, 2, 3, 4, 10, 5)

2.10 groupByKey([numPartitions]))

分组操作,在一个由(K,V)对组成的数据集上调用,返回一个(K,Iterable[V])对的数据集。 

def groupByKey(numPartitions: Int): RDD[(K, Iterable[V])] 

 实例:

scala> val rdd=sc.parallelize(Array((1,2),(1,3),(1,4),(2,3),(2,4),(2,5)),3)
rdd: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[1] at parallelize at <console>:24
scala> val rdd10=rdd.groupByKey()
rdd10: org.apache.spark.rdd.RDD[(Int, Iterable[Int])] = ShuffledRDD[2] at groupByKey at <console>:25
scala> rdd10.collect
res0: Array[(Int, Iterable[Int])] = Array((1,CompactBuffer(2, 3, 4)), (2,CompactBuffer(3, 4, 5))) 

 2.11 reduceByKey(func, [numPartitions])

分组聚合操作, 在一个(K,V)对的数据集上使用,返回一个(K,V)对的数据集。K相同的值,都被使用相同的reduce函数聚合在一起。

实例:相同的key的值加起来 

scala> val rdd11=rdd.reduceByKey(_+_)
rdd11: org.apache.spark.rdd.RDD[(Int, Int)] = ShuffledRDD[4] at reduceByKey at <console>:25
scala> rdd11.collect
res3: Array[(Int, Int)] = Array((1,9), (2,12))

2.12 aggregateByKey(zeroValue)(seqOp, combOp, [numPartitions])

对PairRDD中相同的Key值进行聚合操作,在聚合过程中同样使用了一个中立的初始值。aggregateByKey返回值的类型不需要和RDD中value的类型一致。因为aggregateByKey是对相同Key中的值进行聚合操作,所以aggregateByKey'函数最终返回的类型还是PairRDD,对应的结果是Key和聚合后的值.
def aggregateByKey[U: ClassTag](zeroValue: U, partitioner: Partitioner)(seqOp: (U, V) => U,combOp: (U, U) => U): RDD[(K, U)]  
 aggregateByKey函数的使用,需为它提供以下三个参数:
    1.zeroValue:U,初始值,即聚合的初始值
    2.seqOp: (U, V) => U,seq操作符, 描述如何将V合并到数据结构U
    3.combOp: (U, U) => U,comb操作符,描述如何合并两个数据结构U。
实例1:                            
scala> val rdd=sc.parallelize(List((1,3),(1,2),(1,4),(2,3)),2)
rdd: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[2] at parallelize at <console>:24
scala> val rdd12=rdd.aggregateByKey(0)(math.max(_,_),_+_)
rdd12: org.apache.spark.rdd.RDD[(Int, Int)] = ShuffledRDD[3] at aggregateByKey at <console>:25
scala> rdd12.collect
res1: Array[(Int, Int)] = Array((2,3), (1,7))
 分析过程:

分为两个分区,(1,3),(1,2)会落入0分区,(1,4),(2,3)落入1分区,每个分区分开计算。

初始值为0,所以第一步不对列表值产生影响。
 seqOP:函数是相同key取最大值,0分区的结果为(1,3),1分区的结果为(1,4),(2,3)
 combOP:函数是相同的key的value进行相加,结果为(1,3+4)=>(1,7),(2,3) 

 实例2:

scala> val rdd=sc.parallelize(List((1,3),(1,2),(1,4),(2,3)),3)
rdd: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[4] at parallelize at <console>:24
scala> val rdd12=rdd.aggregateByKey(0)(math.max(_,_),_+_)
rdd12: org.apache.spark.rdd.RDD[(Int, Int)] = ShuffledRDD[5] at aggregateByKey at <console>:25
scala> rdd12.collect
res2: Array[(Int, Int)] = Array((1,9), (2,3))
分析过程:

分为三个分区,(1,3)会落入0分区,(1,2)进入1分区,(1,4),(2,3)落入2分区,每个分区分开计算。

初始值为0,所以第一步不对列表值产生影响。
seqOP:函数是相同key取最大值,0分区的结果为(1,3),1分区的结果为(1,2),2分区的结果为(1,4),(2,3)
combOP:函数是相同的key的value进行相加,结果为(1,3+2+4)=>(1,9),(2,3) 

 2.13 combineByKey

对RDD中的数据集按照key进行聚合操作。聚合操作通过自定义函数提供。  

def combineByKey[C](
createCombiner: V => C,
mergeValue: (C, V) => C,
mergeCombiners: (C, C) => C): RDD[(K, C)] = self.withScope {
combineByKeyWithClassTag(createCombiner, mergeValue, mergeCombiners)(null)
}

三个参数解释:

 createCombiner:在遍历(k,v)时,如果combineByKey第一次遇到值为k的key(类型K),那么将这个(k,v)调用combineCombiner函数,将v转换为C.

 mergeValue:在遍历(k,v)时,如果combineByKey不是第一次遇到值为k的key (类型K),那么将这个(k,v)调用mergeValue函数,它的作用是将v累加到聚合对象(类型为C)中。

mergeCombiners:combineByKey是在分布式环境下执行的,RDD的生个分区单独进行combineByKey操作,最后需要对各个分区的结果进行最后的聚合。

实例如下:

scala> val rdd=sc.parallelize(Array((1,1.0),(1,2.0),(1,3.0),(2,4.0),(2,5.0),(2,6.0)),2)
rdd: org.apache.spark.rdd.RDD[(Int, Double)] = ParallelCollectionRDD[1] at parallelize at <console>:24
scala> val combine=rdd.combineByKey(createCombiner = (v: Double) => (v: Double, 1),
     | mergeValue = (c: (Double, Int), v: Double) => (c._1 + v, c._2 + 1),
     | mergeCombiners = (c1: (Double, Int), c2: (Double, Int)) => (c1._1 + c2._1, c1._2 + c2._2),
     |  numPartitions = 2)
combine: org.apache.spark.rdd.RDD[(Int, (Double, Int))] = ShuffledRDD[2] at combineByKey at <console>:25
scala> combine.collect
res0: Array[(Int, (Double, Int))] = Array((2,(15.0,3)), (1,(6.0,3)))       

 2.14 sortByKey([ascending], [numPartitions])

按key对RDD进行排序,其定义如下: 

def sortByKey(ascending: Boolean = true, numPartitions: Int = self.partitions.length)
: RDD[(K, V)] = self.withScope
{
val part = new RangePartitioner(numPartitions, self, ascending)
new ShuffledRDD[K, V, V](self, part)
.setKeyOrdering(if (ascending) ordering else ordering.reverse)
}
由上可知,该函数有两个参数,第一个参数是排序方式,默认是true(升序),第二个参数可以指定分区,即并行任务数。另外,排序的key需可排序的Ordering

实例: 

scala> val rdd=sc.parallelize(Array((1,3),(2,6),(2,3),(1,2),(1,8),(2,9)))
rdd: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[1] at parallelize at <console>:24
scala> rdd.sortByKey()
res6: org.apache.spark.rdd.RDD[(Int, Int)] = ShuffledRDD[15] at sortByKey at <console>:26
scala> res6.collect
res7: Array[(Int, Int)] = Array((1,3), (1,2), (1,8), (2,6), (2,3), (2,9))

2.15 join(otherDataset, [numPartitions])

 连接操作,将输入数据集(K, V) 和另一数据集 (K, W)进行join, 返回两个集合匹配的(K, (V, W))集合对。即该操作过滤掉不匹配的key,然后返回相同K的V,W集合进行笛卡尔积操作。其定义如下:

def join[W](other: RDD[(K, W)], partitioner: Partitioner): RDD[(K, (V, W))] = self.withScope {
this.cogroup(other, partitioner).flatMapValues( pair =>
for (v <- pair._1.iterator; w <- pair._2.iterator) yield (v, w)
)
}

实例:

scala> val rdd=sc.parallelize(Array((1,2),(1,3),(2,4),(3,6)))
rdd: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[9] at parallelize at <console>:24
scala> val rdd2=sc.parallelize(Array((1,2),(1,5),(2,6)))
rdd2: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[10] at parallelize at <console>:24
scala> val rdd14=rdd.join(rdd2)
rdd14: org.apache.spark.rdd.RDD[(Int, (Int, Int))] = MapPartitionsRDD[13] at join at <console>:27
scala> rdd14.collect
res2: Array[(Int, (Int, Int))] = Array((2,(4,6)), (1,(2,2)), (1,(2,5)), (1,(3,2)), (1,(3,5)))
由此可见,不匹配的key(3,6)未显示。与sql类似,还有左连接、右连接及全连接操作函数:leftOuterJoin、rightOuterJoin及fullOuterJoin。

 2.16 cogroup(otherDataset, [numPartitions])  

类似于join,像上面Join的定义,其底层使用了cogroup. 输入数据集(K, V) 和另一数据集 (K, W)进行cogroup, 将返回格式为(K, (Iterable<V>, Iterable<W>))的数据集,与join不同的是,两个集合中不匹配的Key,也会返回。 
def cogroup[W](other: RDD[(K, W)], partitioner: Partitioner)
: RDD[(K, (Iterable[V], Iterable[W]))]

 实例:

scala> val rdd=sc.parallelize(Array((1,2),(1,3),(2,4),(3,6)))
rdd: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[0] at parallelize at <console>:24
scala> val rdd2=sc.parallelize(Array((1,2),(1,5),(2,6)))
rdd2: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[1] at parallelize at <console>:24
scala> val rdd15=rdd.cogroup(rdd2)
rdd15: org.apache.spark.rdd.RDD[(Int, (Iterable[Int], Iterable[Int]))] = MapPartitionsRDD[3] at cogroup at <console>:27
scala> rdd15.collect
res0: Array[(Int, (Iterable[Int], Iterable[Int]))] = Array((2,(CompactBuffer(4),CompactBuffer(6))), (1,(CompactBuffer(2, 3),CompactBuffer(2, 5))), (3,(CompactBuffer(6),CompactBuffer()))) 
2.17 cartesian(otherDataset)
两个集合进行笛卡尔积
def cartesian[U: ClassTag](other: RDD[U]): RDD[(T, U)] 

实例:

scala> val rdd1=sc.parallelize(Array(1,2,3))
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[18] at parallelize at <console>:24
scala> val rdd2=sc.parallelize(Array(4,5))
rdd2: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[19] at parallelize at <console>:24
scala> val rdd17=rdd1.cartesian(rdd2)
rdd17: org.apache.spark.rdd.RDD[(Int, Int)] = CartesianRDD[20] at cartesian at <console>:27
scala> rdd17.collect
res7: Array[(Int, Int)] = Array((1,4), (1,5), (2,4), (3,4), (2,5), (3,5))

2.18 pipe(command, [envVars])

 可以通过pipe使用shell命令来处理RDD

实例:

scala>  val rdd1=sc.parallelize(1 to 9,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[1] at parallelize at <console>:24
scala> val rdd2=rdd1.pipe("head -n 1").collect
rdd2: Array[String] = Array(1, 4, 7)  

 2.19 coalesce(numPartitions)

 coalesce(numPartitions: Int)将RDD进行重分区,默认只能减少分区,默认不进行shuffle,当开启shuffle时,可以扩大分区。其定义如下:

def coalesce(numPartitions: Int, shuffle: Boolean = false,
partitionCoalescer: Option[PartitionCoalescer] = Option.empty)
(implicit ord: Ordering[T] = null)
: RDD[T]

实例:减少分区

scala> val rdd1=sc.parallelize(1 to 9,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[2] at parallelize at <console>:24
scala> rdd1.partitions.length
res1: Int = 3
scala> val rdd2=rdd1.coalesce(2)
rdd2: org.apache.spark.rdd.RDD[Int] = CoalescedRDD[4] at coalesce at <console>:25
scala> rdd2.partitions.length
res4: Int = 2

实例:扩大分区 

scala> val rdd2=rdd1.coalesce(5)
rdd2: org.apache.spark.rdd.RDD[Int] = CoalescedRDD[1] at coalesce at <console>:25
scala> rdd2.partitions.length
res0: Int = 3
由上面实例可见,不开启shuffle是不能扩大分区的。

实例:开启 shuffle后,可以扩大分区数

scala> val rdd3=rdd1.coalesce(5,true)
rdd3: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[5] at coalesce at <console>:25
scala> rdd3.partitions.length
res1: Int = 5 

 2.20 repartition(numPartitions)

对RDD进行重分区,可以增加分区,也可减少分区,它创建新的分区,会进行shuffer操作 

实例: 

scala> val rdd1=sc.parallelize(1 to 9,3)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[2] at parallelize at <console>:24
scala> val rdd3=rdd1.repartition(5)
rdd3: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[8] at repartition at <console>:25
scala> rdd3.partitions.length
res6: Int = 5

2.21 repartitionAndSortWithinPartitions(partitioner)

根据给定的分区程序对RDD进行重新分区,并在每个生成的分区内按键对记录进行排序。 这比调用重新分区,它要比使用repartition And sortByKey 效率高,这是由于它的排序是在shuffle过程中进行,一边shuffle,一边排序。定义如下:

def repartitionAndSortWithinPartitions(partitioner: Partitioner): RDD[(K, V)] = self.withScope {
new ShuffledRDD[K, V, V](self, partitioner).setKeyOrdering(ordering)
}

使用repartitionAndSortWithinPartitions时,需要自己传入一个分区器,这个分区器可以使用系统提供的,也可以是自定义的,以下实例我们使用系统的HashPartitioner 

实例: 

scala> import org.apache.spark.HashPartitioner 
import org.apache.spark.HashPartitioner
scala> val rdd=sc.parallelize(Array(2,4,8,6,23,12,123,98,18))
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[1] at parallelize at <console>:25
scala> rdd.zipWithIndex().repartitionAndSortWithinPartitions(new HashPartitioner(1)).foreach(println)
(2,0)
(4,1)
(6,3)
(8,2)
(12,5)
(18,8)
(23,4)
(98,7)
(123,6) 

3. 转换操作

3.1 reduce(func) 

对数据集中每个元素执行指定的聚集函数(有两个输入参数,一个返回值) ,这个函数必须是可交换的和组合的。

实例: 

scala>  val arrays=Array(1,2,3,4,5,6,7,8,9,10);
arrays: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala>  val rdd=sc.parallelize(arrays,3)
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[1] at parallelize at <console>:26
scala> val sum=rdd.reduce(_+_)
sum: Int = 55

3.2 collect()

将数据集的内容以Array数据的形式返回

实例:

scala> val rdd=sc.parallelize(1 to 9,3)
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24
scala> rdd.collect
res0: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)

 3.3 count()

返回数据集元素的个数。

实例:

scala> rdd.count
res0: Long = 9

3.4 first()

返回集合中的第一个元素。

实例: 

scala> val rdd=sc.parallelize(1 to 9,3) 
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24
scala> rdd.first
res2: Int = 1

3.5 take(n)

返回集合中前n个元素的数组。

3.6 takeSample(withReplacement, num, [seed])

返回包含随机的num个元素的数组。第一个参数withReplacement是抽样时是否放回,第二个参数num会精确指定抽样数,而不是比例.第三个参数seed是随机种子。

实例:

scala> rdd.take(3)
res3: Array[Int] = Array(1, 2, 3) 

3.7  takeOrdered(n, [ordering]) 

按自然顺序或者自定义比较器返回第1到n元素的数组

实例:

scala> rdd.takeOrdered(5)

res6: Array[Int] = Array(1, 2, 3, 4, 5)  

 3.8 saveAsTextFile(path) 

把数据集中的元素转换为文本文件写到指定的目录(本地系统、HDFS或者其它hadoop支持的文件系统).Spark将每个元素调用toString方法转换为文本文件中的一行。

 实例:将数据转为文本存储到hdfs中。

scala> val rdd=sc.parallelize(1 to 9,3)
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[1] at parallelize at <console>:24  
scala> rdd.saveAsTextFile("hdfs://master:9000/number")
hdfs中查看是否有文件存在,并进行3个分区存储  
[root@master ~]# hdfs dfs -ls /number.txt
Found 4 items
-rw-r--r--   3 root supergroup          0 2018-10-29 14:45 /number.txt/_SUCCESS
-rw-r--r--   3 root supergroup          6 2018-10-29 14:45 /number.txt/part-00000
-rw-r--r--   3 root supergroup          6 2018-10-29 14:45 /number.txt/part-00001
-rw-r--r--   3 root supergroup          6 2018-10-29 14:45 /number.txt/part-00002
[root@master ~]# hdfs dfs -ls /number
Found 4 items
-rw-r--r--   3 root supergroup          0 2018-10-29 14:47 /number/_SUCCESS
-rw-r--r--   3 root supergroup          6 2018-10-29 14:47 /number/part-00000
-rw-r--r--   3 root supergroup          6 2018-10-29 14:47 /number/part-00001
-rw-r--r--   3 root supergroup          6 2018-10-29 14:47 /number/part-00002
[root@master ~]# hdfs dfs -cat /number/part-00000
1
2
3
3.9 saveAsSequenceFile(path)  
 类型于saveAsTextFile,用于将RDD中元素转换为 hadoop SequenceFile保存到指定的目录(本地系统、HDFS或者其它hadoop支持的文件系统)。  
在RDD的键值对实现了hadoop的Writable接口是可用的,在Scala中,即类型可以隐式转为Writable(Spark可转换的基本类型如Int,Double,String等)  
 3.10 saveAsObjectFile
 用于将RDD中的元素序列化成对象,存储到文件中。

 3.11 countByKey()

对于类型 (K, V)的RDD. 返回一个 (K, Int)的map,Int为K的个数。
实例: 

scala> val rdd=sc.parallelize(Array((1,2),(1,3),(1,5),(2,4),(2,6),(3,8)),3)

rdd: org.apache.spark.rdd.RDD[(Int, Int)] = ParallelCollectionRDD[1] at parallelize at <console>:24
scala> rdd.countByKey()
res2: scala.collection.Map[Int,Long] = Map(3 -> 1, 1 -> 3, 2 -> 2)     

3.12 foreach(func)

对数据集中每个元素执行func函数。
实例:
scala> val rdd=sc.parallelize(1 to 6,3)
rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[5] at parallelize at <console>:24
scala> rdd.foreach(x=>println(x*2))
2
4
10
12
6
8

参考文献:

http://spark.apache.org/docs/latest/rdd-programming-guide.html

Spark MLlib机器学习 -黄美灵

 版权声明:本文为博主原创文章,转载请注明出处:https://www.cnblogs.com/abcdwxc/p/9867475.html

posted on 2018-10-28 21:56  王晓成  阅读(2922)  评论(0编辑  收藏  举报