spark中的转换算子1

spark转换算子1举例:

1)map算子:
将原来 RDD 的每个数据项通过 map 中的用户自定义函数 f 映射转变为一个新的元素。源码中 map 算子相当于初始化一个 RDD, 新 RDD 叫做 MappedRDD(this, sc.clean(f))。

package Test

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

import scala.util.Random

object Testforyiele {
  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("mapRDD")

    val context: SparkContext = new SparkContext(conf)
    //生成20个[0,9]之间的整数
    var res = for (i <- 1 to 20) yield {
      Random.nextInt(10)
    }
    //创建一个RDD,类型是Int
    val ListRDD: RDD[Int] = context.makeRDD(res)

    //map算子,例如在ListRDD集合中每个元素的后缀加入字符串abc
    val MapRDD: RDD[String] = ListRDD.map(_ + "abc")

    MapRDD.collect().foreach(datas => print(datas + "\t"))

  }
}

输出:4abc 6abc 8abc 5abc 2abc 6abc 5abc 6abc 9abc 9abc 0abc 7abc 6abc 9abc 1abc 3abc 4abc 7abc 1abc 3abc
2)flatMap算子:
**将原来 RDD 中的每个元素通过函数 f 转换为新的元素,并将生成的 RDD 的每个集合中的元素合并为一个集合,内部创建 FlatMappedRDD(this,sc.clean(f))。
  **

  val ListRDD: RDD[Array[Any]] = context.makeRDD(Array(Array("a",1,2,45),Array(4,7,18,"oop","om")))
   
    //注意类型 RDD[Any]一维与RDD[Array[Any]]二维达到了降维效果,这算子也叫扁平化操作
   val flatMapRDD: RDD[Any] = ListRDD.flatMap(x=>x)

输出: a 1 2 45 4 7 18 oop om
3)mapPartitions
mapPartitions 函 数 获 取 到 每 个 分 区 的 迭 代器,在 函 数 中 通 过 这 个 分 区 整 体 的 迭 代 器 对整 个 分 区 的 元 素 进 行 操 作。 内 部 实 现 是 生 成
MapPartitionsRDD

 val ListRDD: RDD[Any] = context.makeRDD(List("sbv","om","shuffle",3,4))

    //    f: Iterator[T] => Iterator[U]
    //      遍历每一个分区(将一个一个分区看作一个整体进行逻辑处理)
    //    效率比map算子要快,隐患是可能会内存溢出
   val PartitionsRDD: RDD[String] = ListRDD.mapPartitions(Partitions=>Partitions.map(data=>data+"s"))

4)mapPartitionWithIndex
函数作用同mapPartitions,不过提供了两个参数,第一个参数为分区的索引。

 //生成6个[0,9]之间的整数
    var res = for (i <- 1 to 6) yield {
      Random.nextInt(10)
    }


  val ListRDD: RDD[Any] = context.makeRDD(res,2)

    //f: (Int, Iterator[T]) => Iterator[U],获取数据在哪一个分区,
    //二元组,参数一是分区号(Int类型),参数二是数据(Iterator[Int]类型,根据ListRDD的RDD类型推断
    val PartitionsWithIndexRDD: RDD[(Any, String)] = ListRDD.mapPartitionsWithIndex {
      case (nums, datas) =>
        datas.map((_, "分区:" + nums))
    }

输出:
(7,分区:0)
(9,分区:0)
(1,分区:0)
(0,分区:1)
(5,分区:1)
(4,分区:1)
4)glom

glom函数将每个分区形成一个数组,内部实现是返回的GlommedRDD。

 //生成20个[0,9]之间的整数
var res = for (i <- 1 to 20) yield{
  Random.nextInt(10)
}
val ListRDD: RDD[Int] = context.makeRDD(res)

//将一个分区的数据放入到Array数组中
val glomRDD: RDD[Array[Int]] = ListRDD.glom()
glomRDD.collect().foreach(datas=>println(datas.mkString(",")))

输出:
8,3
1,2,8
1,0
0,2,1
5,0
9,4,3
2,7
6,5,2
7) groupBy
  groupBy :将元素通过函数生成相应的 Key,数据就转化为 Key-Value 格式,之后将 Key 相同的元素分为一组。

//随机生成30个[0-99]之间的整数并以Vector集合类型进行返回给res
val res = for (i <- 1 to 30) yield {
  Random.nextInt(100)
}
val ListRDD: RDD[Int] = context.makeRDD(res)
//按照指定的规则进行分组,将ListRDD集合中每一个元素模以5,结果相同则视为一个key
//返回一个二元组 Int 类型指的是返回模以5的结果,Iterable[Int])指的是返回相同key(模以5的结果)的集合
val groupRDD: RDD[(Int, Iterable[Int])] = ListRDD.groupBy(x => x % 5)
groupRDD.collect().foreach(println)

输出:
(0,CompactBuffer(15, 85, 70))
(1,CompactBuffer(41, 6, 31, 41, 96, 46))
(2,CompactBuffer(37, 7, 82, 37, 17, 72, 57))
(3,CompactBuffer(8, 98, 98, 78, 8))
(4,CompactBuffer(54, 34, 4, 24, 54, 59, 44, 44, 94))
8) filter
filter 函数功能是对元素进行过滤,对每个 元 素 应 用 f 函 数, 返 回 值 为 true 的 元 素 在RDD 中保留,返回值为 false 的元素将被过滤掉。 内 部 实 现 相 当 于 生 成 FilteredRDD(this,sc.clean(f))

val ListRDD: RDD[String] = context.makeRDD(Array(“Tom”,“Lisa”,“Python”,“Sparck”,“Scala”))
//将ListRDD集合中包含S字符取出,其他过滤掉
val filterRDD: RDD[String] = ListRDD.filter(x => x.contains(“S”))
filterRDD.collect().foreach(println)

输出:
Sparck
Scala
9)distinct
  distinct将RDD中的元素进行去重操作.

val ListRDD: RDD[Any] = context.makeRDD(Array(2,1,3,2,1,"Tom","Python","Python"))
val distinctRDD: RDD[Any] = ListRDD.distinct()
    distinctRDD.collect().foreach(println)

输出:1
Tom
2
3
Python
结果貌似与我们想得不一样,distinct操作有shuffle的读写操作,那就有数据重组(洗牌)操作,实际上我们有这个转换操作时,它必须等待所有分区的数据全部读完,才会进行这个转换操作,不同于其他转换算子,map算子不需要等待下一个分区,可以这样说map算子有并行机制,但distinct算子没有并行机制(我们也必须等待所有分区的数据读完,才能去重)
11) sample
sample 将 RDD 这个集合内的元素进行采样,获取所有元素的子集。用户可以设定是否有放回的抽样、百分比、随机种子,进而决定采样方式。内部实现是生成 SampledRDD(withReplacement, fraction, seed)。

val ListRDD: RDD[Int] = context.makeRDD(1 to 20)
//随机抽样,参数一,是否放回数据,true放回,false不放回
//fraction参数并不是总体的百分比量,但它的参数越大,抽样数量越大,
//seed表示一个种子(这点可以再次运行会和上一次运行结
//果相同,运行几次也是一样,伪随机数)
val SampleRDD: RDD[Int] = ListRDD.sample(false,0.5,5)

猜你喜欢

转载自blog.csdn.net/changshupx/article/details/108446077