spark算子总结

spark算子总结

  • RDD介绍

rdd是(resilient distribute dataset)弹性分布式数据集
代表一个不可变,可分区,里面的元素可并行计算的集合
对rdd的改动,只能通过转换算子,转换成一个新的形态的rdd,所以调用转换算子返回一个新的rdd

  • Spark 算子的分类

spark的算子分为行动算子和转换算子
调用转换算子是逻辑上的传递,并没有真正运算,实际数据并没有变化,调用行动算子后,才会发给执行器,才会实际在在执行器中执行运算。

  • Spark RDD的创建

编译环境:IDEA

  • 先获得一个sc对象
val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("Demo1")
val sc = new SparkContext(sparkConf)
  • rdd对象的创建 有两种方式makeRDD和parallize
val rdd: RDD[Int] = sc.makeRDD(1 to 10, 3)
val rdd: RDD[Int] = sc.parallelize(1 to 10, 3)
  • 转换算子

1.map算子
从A类型到B类型的映射,一般用来RDD格式转换,rdd中的元素整体上分为value类型和key-value类型

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"))
val mapRDD: RDD[(String, Int)] = rdd.map((_, 1))
mapRDD.foreach(println)

result
(李四,1)
(张三,1)
(张三,1)
(李四,1)
(王五,1)
(张三,1)

2.mapPartitions是按分区数对每个分区的进行处理的,如果有M个分区,那么每次处理一个分区,处理M次,map是按数据条数处理的,有n条数据,每次就处理N条数据,map处理n次,内存足够大时,mapPartitions比map效率高

	val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    val mapPRdd: RDD[(String, Int)] = rdd.mapPartitions(iter => iter.map((_, 1)))
    mapPRdd.foreach(println)

result
(王五,1)
(李四,1)
(张三,1)
(张三,1)
(张三,1)
(李四,1)

3,mapPartitionsWithIndex

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val mapPI: RDD[(Int, (String, Int))] = rdd.mapPartitionsWithIndex((i, iter) => {
      iter.map((_, 1)).map((i, _))
    })

result
(2,(李四,1))
(0,(张三,1))
(1,(王五,1))
(0,(李四,1))
(2,(张三,1))
(1,(张三,1))

4.glom算子
将每一个分区的数据,装载到一个array中

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
val glomRdd: RDD[Array[String]] = rdd.glom()
    var index=0
    for (arr <- glomRdd.collect()) {
      index+=1
      println("第"+index+"分区的元素有:")
      for (elem <- arr) {
        println(elem)
      }
    }

result
第1分区的元素有:
张三
李四
第2分区的元素有:
王五
张三
第3分区的元素有:
李四
张三

groupBy算子
按传入函数的返回值分组,将key值相同的一组放在一个迭代器里

	val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.groupBy(x=>x).collect().foreach(println)

result
(李四,CompactBuffer(李四, 李四))
(王五,CompactBuffer(王五))
(张三,CompactBuffer(张三, 张三, 张三))

filter算子
过滤出满足条件的数据,返回一个新的RDD

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.filter(x=>x.contains("三")).foreach(println)

result
张三
张三
张三

sample算子
指定随机种子随机抽样,期望为fraction,withReplace设定抽样后是否放回,seed用于指定随机数种子

val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("Demo1")
    val sc = new SparkContext(sparkConf)
    val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.sample(fraction = 1,withReplacement = true,seed = 10L).foreach(println)

result
李四
李四
王五
张三
张三
张三

distinct
去重

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.distinct().foreach(println)

result
李四
张三
王五

union算子求并集

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    val disRdd: RDD[String] = rdd.distinct()
    rdd.union(disRdd).foreach(println)

result
王五
李四
张三
张三
张三
李四
张三
李四
王五

subtract算子

去掉相同的数据,不同的保留到新rdd返回

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    val disRdd: RDD[String] = rdd.distinct()
    rdd.subtract(disRdd).foreach(println)

result

intersection算子
求交集

    val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    val disRdd: RDD[String] = rdd.distinct()
    rdd.intersection(disRdd).foreach(println)

result
张三
李四
王五

cartesian
笛卡尔积

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    val disRdd: RDD[String] = rdd.distinct()
    rdd.cartesian(disRdd).foreach(println)

result
(王五,李四)
(李四,李四)
(王五,张三)
(张三,张三)
(张三,李四)
(李四,张三)
(张三,王五)
(李四,王五)
(王五,王五)
(李四,李四)
(张三,张三)
(李四,王五)
(李四,张三)
(张三,李四)
(张三,王五)
(张三,张三)
(张三,李四)
(张三,王五)

zip算子
合并两个数据集为k,v形式,要求两个数据集的分区数和数据总数相同

    val rdd1: RDD[Int] = sc.makeRDD(1 to 10, 2)
    val rdd2: RDD[Int] = sc.makeRDD(11 to 20,2)
    rdd1.zip(rdd2).collect().foreach(println)

reslut
(1,11)
(2,12)
(3,13)
(4,14)
(5,15)
(6,16)
(7,17)
(8,18)
(9,19)
(10,20)

coalesce
缩小分区,通常用于大数据集过滤后,提高小数据集的执行效率
第二个可以选择是否shuffle,使用可以让合并分区的数据均匀,不使用则能避免数据倾斜,提高执行效率

    val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    val coalRdd: RDD[String] = rdd.coalesce(2, false)
    coalRdd.saveAsTextFile("1")

spark算子总结_第1张图片

result
0000
张三
李四
0001
王五
张三
李四
张三

repartiton
根据分区数,重新通过打乱重组所有的数据

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.repartition(4).saveAsTextFile("2")

spark算子总结_第2张图片
reduceByKey算子
根据key进行分组,对相同key的value值传入函数进行累积计算,比如累加累乘

sortBy算子
根据传入函数的返回结果进行排序

	val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.map((_,1)).reduceByKey(_+_).sortBy(x=>x._2,false).collect().foreach(println)

result
(张三,3)
(李四,2)
(王五,1)

groupByKey算子

	val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.map((_,1)).groupByKey().collect().foreach(println)

result
(李四,CompactBuffer(1, 1))
(王五,CompactBuffer(1))
(张三,CompactBuffer(1, 1, 1))

aggregateByKey算子
第一参数为初始值,第二个为分区内操作,第二个为分区间操作

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.map((_, 1)).aggregateByKey(0)(_ + _, _ + _).collect().foreach(println)

result
(李四,2)
(王五,1)
(张三,3)

foldByKey算子
相当于分区内和分区间操作相同的aggregateByKey算子,上面代码和下面代码效果一样

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.map((_, 1)).foldByKey(0)(_+_).collect().foreach(println)

combinByKey算子

mapValues算子
争对value值进行操作

val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    rdd.map((_,1)).mapValues(k=>k+1).collect().foreach(println)

PartitionBy
按照分区器进行分区,分区器有三种HashPartitioner(按key的hashcode值对分区数取余分),RangePartitioner (范围分区器),自定义分区器
自定义分区器,写一个类继承自Partitioner

	val rdd: RDD[String] = sc.makeRDD(Array("张三","李四","王五","张三","李四","张三"),3)
    val pRDD: RDD[(String, Int)] = rdd.map((_, 1)).partitionBy(new HashPartitioner(2))
    val rdd: RDD[(Int, Int)] = sc.parallelize(List((1, 1), (5, 10), (5, 9), (2, 4), (3, 5), (3, 6), (4, 7), (4, 8), (2, 3), (1, 2)))
    rdd.partitionBy(new RangePartitioner(3,rdd)).collect().foreach(println)

result
(1,1)
(2,4)
(2,3)
(1,2)
(3,5)
(3,6)
(4,7)
(4,8)
(5,10)
(5,9)

自定义分区器

val rdd: RDD[(Int, Int)] = sc.parallelize(List((1, 1), (5, 10), (5, 9), (2, 4), (3, 5), (3, 6), (4, 7), (4, 8), (2, 3), (1, 2)))
    rdd.partitionBy(new MyPartitioner(3)).saveAsTextFile("3")

class MyPartitioner(num:Int) extends Partitioner{
  override def numPartitions: Int = num

  override def getPartition(key: Any): Int = {
    if(key.toString.toInt>4){
      2
    }else if(key.toString.toInt>1){
      1
    }else{
      0
    }
  }
}

spark算子总结_第3张图片
spark算子总结_第4张图片
spark算子总结_第5张图片
spark算子总结_第6张图片

你可能感兴趣的:(学习,Java,spark)