Spark RDD 函数大全(1-10)

1、RDD 操作详解
启动 spark-shell spark-shell--masterspark://hdp-node-01:7077
1.1 基本转换

  1. map
    map 是对 RDD 中的每个元素都执行一个指定的函数来产生一个新的 RDD。 任何 原 RDD 中的元素在新 RDD 中都有且只有一个元素与之对应。 举例: scala>vala=sc.parallelize(1to9,3) scala>valb=a.map(x=>x*2) scala>a.collect res10:Array[Int]=Array(1,2,3,4,5,6,7,8,9) scala>b.collect res11:Array[Int]=Array(2,4,6,8,10,12,14,16,18) 上述例子中把原 RDD 中每个元素都乘以 2 来产生一个新的 RDD。
  2. filter
    filter 是对 RDD 中的每个元素都执行一个指定的函数来过滤产生一个新的 RDD。 任何原 RDD 中的元素在新 RDD 中都有且只有一个元素与之对应。
    valrdd=sc.parallelize(List(1,2,3,4,5,6)) valfilterRdd=rdd.filter(_>5) filterRdd.collect()//返回所有大于 5 的数据的一个 Array, Array(6,8,10,12)
  3. flatMap
    与 map 类似,区别是原 RDD 中的元素经 map 处理后只能生成一个元素,而原 RDD 中的元素经 flatmap 处理后可生成多个元素来构建新 RDD。举例:对原 RDD 中的每个元素 x 产生 y 个元素(从 1 到 y,y 为元素 x 的值) scala>vala=sc.parallelize(1to4,2) scala>valb=a.flatMap(x=>1tox)
    scala>b.collect res12:Array[Int]=Array(1,1,2,1,2,3,1,2,3,4)
  4. mapPartitions
    mapPartitions 是 map 的一个变种。map 的输入函数是应用于 RDD 中每个元素, 而 mapPartitions 的输入函数是应用于每个分区,也就是把每个分区中的内容作 为整体来处理的。 它的函数定义为: def mapPartitions[U: ClassTag](f: Iterator[T] => Iterator[U], preservesPartitioning: Boolean=false):RDD[U] f 即为输入函数,它处理每个分区里面的内容。每个分区中的内容将以 Iterator[T] 传递给输入函数 f, f 的输出结果是 Iterator[U]。最终的 RDD 由所有分区经过输入 函数处理后的结果合并起来的。 举例: scala>vala=sc.parallelize(1to9,3) scala>defmyfuncT:Iterator[(T,T)]={ varres=List(T,T) varpre=iter.next while(iter.hasNext){ valcur=iter.next res.::=(pre,cur) pre=cur } res.iterator } scala>a.mapPartitions(myfunc).collect res0:Array[(Int,Int)]=Array((2,3),(1,2),(5,6),(4,5),(8,9),(7,8)) 上述例子中的函数myfunc是把分区中一个元素和它的下一个元素组成一个Tuple。 因为分区中最后一个元素没有下一个元素了,所以(3,4)和(6,7)不在结果中。 mapPartitions 还有些变种,比如 mapPartitionsWithContext,它能把处理过程中的 一些状态信息传递给用户指定的输入函数。还有 mapPartitionsWithIndex,它能 把分区的 index传递给用户指定的输入函数。
  5. mapPartitionsWithIndex
    def mapPartitionsWithIndex[U](f: (Int, Iterator[T]) => Iterator[U], preservesPartitioning:Boolean=false)(implicitarg0:ClassTag[U]):RDD[U] 函数作用同 mapPartitions,不过提供了两个参数,第一个参数为分区的索引。
    varrdd1=sc.makeRDD(1to5,2) //rdd1 有两个分区 varrdd2=rdd1.mapPartitionsWithIndex{ (x,iter)=>{ varresult=ListString vari=0 while(iter.hasNext){ i+=iter.next() } result.::(x+"|"+i).iterator
    }
    } //rdd2 将 rdd1 中每个分区的数字累加,并在每个分区的累加结果前面加了分区 索引 scala>rdd2.collect res13:Array[String]=Array(0|3,1|12)
  6. mapWith
    mapWith 是 map 的另外一个变种,map 只需要一个输入函数,而 mapWith 有两 个输入函数。它的定义如下: def mapWith[A: ClassTag, U: ](constructA: Int => A, preservesPartitioning: Boolean = false)(f:(T,A)=>U):RDD[U] 第一个函数 constructA 是把 RDD 的 partitionindex(index 从 0 开始)作为输入, 输出为新类型 A; 第二个函数 f 是把二元组(T,A)作为输入(其中 T 为原 RDD 中的元素,A 为第一个 函数的输出),输出类型为 U。 举例:把 partitionindex 乘以 10 加 2,作为新的 RDD 的元素。 valx=sc.parallelize(List(1,2,3,4,5,6,7,8,9,10),3) x.mapWith(a=>a*10)((b,a)=>(b,a+2)).collect 结果: (1,2) (2,2) (3,2) (4,12)
    (5,12) (6,12) (7,22) (8,22) (9,22) (10,22)
  7. flatMapWith
    flatMapWith 与 mapWith 很类似,都是接收两个函数,一个函数把 partitionIndex 作为输入,输出是一个新类型 A;另外一个函数是以二元组(T,A)作为输入,输 出为一个序列,这些序列里面的元素组成了新的 RDD。它的定义如下: defflatMapWith[A:ClassTag, U: ClassTag](constructA:Int =>A, preservesPartitioning: Boolean=false)(f:(T,A)=>Seq[U]):RDD[U] 举例: scala>vala=sc.parallelize(List(1,2,3,4,5,6,7,8,9),3) scala>a.flatMapWith(x=>x,true)((x,y)=>List(y,x)).collect res58:Array[Int]=Array(0,1,0,2,0,3,1,4,1,5,1,6,2,7,2, 8,2,9)
  8. coalesce
    def coalesce(numPartitions: Int, shuffle: Boolean = false)(implicit ord: Ordering[T] = null):RDD[T] 该函数用于将 RDD 进行重分区,使用 HashPartitioner。 第一个参数为重分区的数目,第二个为是否进行 shuffle,默认为 false; 以下面的例子来看: scala>vardata=sc.parallelize(1to12,3) scala>data.collect scala>data.partitions.size scala>varrdd1=data.coalesce(1) scala>rdd1.partitions.size scala>varrdd1=data.coalesce(4) scala>rdd1.partitions.size res2:Int=1 //如果重分区的数目大于原来的分区数,那么必须指定 shuffle 参 数为 true,//否则,分区数不便 scala>varrdd1=data.coalesce(4,true) scala>rdd1.partitions.size
    res3:Int=4
  9. repartition
    defrepartition(numPartitions:Int)(implicitord:Ordering[T]=null):RDD[T] 该函数其实就是 coalesce 函数第二个参数为 true 的实现 scala>vardata=sc.parallelize(1to12,3) scala>data.collect scala>data.partitions.size scala>varrdd1=data.repartition(1) scala>rdd1.partitions.size scala>varrdd1=data.repartition(4) scala>rdd1.partitions.size res3:Int=4
  10. randomSplit
    def randomSplit(weights: Array[Double], seed: Long = Utils.random.nextLong): Array[RDD[T]] 该函数根据 weights 权重,将一个 RDD 切分成多个 RDD。 该权重参数为一个 Double 数组 第二个参数为 random 的种子,基本可忽略。 scala>varrdd=sc.makeRDD(1to12,12) rdd:org.apache.spark.rdd.RDD[Int]=ParallelCollectionRDD[16]atmakeRDDat:21
    scala>rdd.collect res6:Array[Int]=Array(1,2,3,4,5,6,7,8,9,10)
    scala>varsplitRDD=rdd.randomSplit(Array(0.5,0.1,0.2,0.2)) splitRDD: Array[org.apache.spark.rdd.RDD[Int]] = Array(MapPartitionsRDD[17] at randomSplitat:23, MapPartitionsRDD[18]atrandomSplitat:23, MapPartitionsRDD[19]atrandomSplitat:23, MapPartitionsRDD[20]atrandomSplitat:23)
    //这里注意:randomSplit 的结果是一个 RDD 数组
    scala>splitRDD.size res8:Int=4 //由于 randomSplit 的第一个参数 weights 中传入的值有 4 个,因此,就会切分成 4 个 RDD, //把原来的 rdd 按照权重 0.5,0.1,0.2,0.2,随机划分到这 4 个 RDD 中,权重高的 RDD,划分到//的几率就大一些。 //注意,权重的总和加起来为 1,否则会不正常 scala>splitRDD(0).collect res10:Array[Int]=Array(1,4)
    scala>splitRDD(1).collect res11:Array[Int]=Array(3)
    scala>splitRDD(2).collect res12:Array[Int]=Array(5,9)
    scala>splitRDD(3).collect res13:Array[Int]=Array(2,6,7,8,10)

推荐阅读更多精彩内容