spark重要的几个算子

spark中有几个算子比较重要,开发中不是很常用,但很多算子的底层都是依靠这几个算子实现的,比如CombineByKey,像reduceByKey底层是combineByKey实现的。
首先介绍combineByKey
这个算子 主要需要三个参数,第一个是对每个分区中每个key的第一个值 进行初始化,也就是每个分区内,有多少个key就会执行多少次这个初始化
object CombineByKeyTest01 {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf
    conf.setMaster("local").setAppName("test")
    val sc=new SparkContext(conf)
    
    val rdd1=sc.parallelize(List(("a","2"),("a","3"),("a","4"),("b","3"),("b","4")),2)
    
    rdd1.foreachPartition(f =>{
      while(f.hasNext){
        print(f.next())
      }
    })
    val rdd2=rdd1.combineByKey(x=>{println("fff=="+x);(x.toInt*2).toString()},(x1:String,x2:String)=>(x1.toInt+x2.toInt).toString(),(s1:String,s2:String)=>(s1.toInt+s2.toInt).toString())
    
    rdd2.foreachPartition(f=>{
      while(f.hasNext){
        print(f.next())
      }
    })
    
    
    sc.stop()
  }
第一个分区为(a,2)(a,3),第二个分区为(a,4)(b,3)(b,4)
对于第一个分区 ,首先执行第一步,即(a,4),然后聚合,得出(a,7)
对于第二个分区,首先执行第一步,(a,8),(b,6),(b,4)然后聚合得出(a,8),(b,10)
最后,对所有分区进行聚合,调用第三个参数对于的函数,得出(a,15),(b,10)
接下来介绍Aggregate
这个算子主要是三个参数,第一个参数是初始值,第二个参数进行分区内聚合,第三个参数是对每个分区最后的结果进行聚合
object AggregateTest01 {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf
    conf.setMaster("local").setAppName("test")
    val sc=new SparkContext(conf)
    
    val rdd1=sc.parallelize(List("1","2","3","4","5","6","7"),2)
    
    rdd1.foreachPartition(f =>{
      while(f.hasNext){
        print(f.next())
      }
    })
    //aggregate操作
    val result=rdd1.aggregate("3")(seqOphyj,combOphyj)
    
    println(result)
    
    sc.stop()
  }
  //每个分区中 每个元素 乘以2 然后相加  进行分区内聚合操作
  def seqOphyj(s1:String,s2:String):String={
    val ss1=(2*s1.toInt+2*s2.toInt).toString()
    ss1
  }
  //每个分区的结果 与初始值 进行相加操作
  def combOphyj(s1:String,s2:String):String={
    val ss1=(s1.toInt+s2.toInt).toString()
    ss1
  }
}
第一个分区为1,2,3 第二个分区为4,5,6,7
对于第一个分区,首先进行第二个函数 即3*2+1*2=8  8*2+2*2=20 20*2+3*2=46
对于第二个分区,首先进行第二个函数, 3*2+4*2=14  14*2+5*2=38  38*2+6*2=88  88*2+7*2=190
然后进行调用第三个函数 3+46+190=239
接下来是AggregateByKey
这个算子基本和Aggregate类似,是对相同key的value进行聚合,但还是有区别的,区别在下面说。
object AggregateByKeyTest01 {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf
    conf.setMaster("local").setAppName("test")
    val sc=new SparkContext(conf)
    val rdd1=sc.parallelize(List(("1","2"),("1","3"),("1","4"),("2","3"),("2","4")),2)
    rdd1.foreachPartition(f =>{
      while(f.hasNext){
        print(f.next())
      }
    })
    val rdd2=rdd1.aggregateByKey("2")(seqOphyj, combOphyj)
    rdd2.foreachPartition(f =>{
      while(f.hasNext){
        print(f.next())
      }
    })
    sc.stop()
  }
  //每个分区中 每个元素 乘以2 然后相加  进行分区内聚合操作
  def seqOphyj(s1:String,s2:String):String={
    val ss1=(2*s1.toInt+2*s2.toInt).toString()
    println("seq="+s1+"&&"+s2+"====="+ss1)
    ss1
  }
  //每个分区的结果 与初始值 进行相加操作
  def combOphyj(s1:String,s2:String):String={
    val ss1=(s1.toInt+s2.toInt).toString()
    println("com="+s1+"&&"+s2+"====="+ss1)
    ss1
  }
}
第一个分区为(1,2)(1,3),第二个分区为(1,4)(2,3)(2,4)
首先计算第一个分区。对于key1,value为(2*2+2*2)*2+3*2=22
再计算第二个分区,对于key1,value为2*2+4*2=12,对于key2,value为(2*2+3*2)*2+4*2=28
计算第三个方法,为(1,34)(2,28),它与Aggregate的不同点在于第三个函数执行的时候。默认值不参与运算,而aggregate是参与的。

猜你喜欢

转载自hanyingjun318.iteye.com/blog/2319287