cogroup算子

cogroup:协分组

val rdd1 = sc.parallelize(List(("tom",1),("tom",2),("jerry",3),("kitty",2)))

--->(String, Int)

val rdd2 = sc.parallelize(List(("jerry",2),("tom",1),("jerry",3),("kitty",2)))

---->[(String, Int)]

val rdd3 = rdd1.cogroup(rdd2)

---->rdd.RDD[(String, (Iterable[Int], Iterable[Int]))

 Array[(String, (Iterable[Int], Iterable[Int]))] = Array((tom,(CompactBuffer(1, 2),CompactBuffer(1))), (kitty,(CompactBuffer(2),CompactBuffer(2))), (jerry,(CompactBuffer(3),CompactBuffer(2, 3))))

结果:把key相同的value全部放到一个特殊的集合里面,,与group类似,但是cogroup里面的value有多个迭代器,

注意到结果的两个迭代器没第一个迭代器装第一个RDD里面key相同的value,第二个迭代器装的是第二个RDD里面的key相同的value,

总结:group是对一个RDD进行操作,在一个RDD里面的多个分区进行shuffle,然后分到同一个组里面,

,cogroup是对多个RDD进行操作,通过shuffle,然后把key相同的数据搞到一起,并且它的value不是一个迭代器,如果有两个 迭代器,那么返回的是一个对偶元组,对偶元组里面有两个compactBufffer,和两个Iterator,如果有多个RDD,那么在cogroup的时候会产生多个compactBuffer,每个compactBufffer里面装有多个相同的key,聚合到一起存储对应value的值得特殊的集合,并且对应多个Iterator.

 

distinct及其底层逻辑

1.distinct可以调用k-v类型的数据

2.底层把数据跟null合在一起,变成元组,在调用reduceByKey,里面传的是,把相同key的value第一个拿过来,然后还是返回第一个,两个相同的key的value进行两两迭代,但是只保留其中一个,

 

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

    val sc = new SparkContext(conf)
    val nums: RDD[Int] = sc.parallelize(List(1, 2, 2, 3, 4, 5, 6, 7, 7, 7, 8, 8, 6, 6, 4, 8))

    val dietincted = nums.distinct()

    val res = dietincted.collect()
    println(res.toBuffer)
    sc.stop()
  }
  

 

通过reducedByKey实现distinct的功能

调用map添加null ,调用reduceByKey,分组去重,最后返回该元素,在调用map返回元组的第一个元素

   val conf = new SparkConf().setAppName("ReduceByKey").setMaster("local[*]")

    val sc = new SparkContext(conf)
    val nums: RDD[Int] = sc.parallelize(List(1, 2, 2, 3, 4, 5, 6, 7, 7, 7, 8, 8, 6, 6, 4, 8))

    val dietincted = nums.distinct()

    /*val res = dietincted.collect()
    println(res.toBuffer)
    sc.stop()*/
    //使用reduceByKey实现distinct的功能
    //对每个数据添加null,reduceByKey,先局部去重然后全局去重,最终只返回Key,然后只要元组里面的第一个数据
    val reduced = nums.map((_, null)).reduceByKey((x, _) => x).map(_._1)
    println(reduced.collect().toBuffer)
    
  }

 

 

 cogroup

一个RDD作为参数传到另外一个RDD里面,返回的也是一个RDD,如果数据在RDD里面出现一次或多次,那么就会,就会传到,

如果在第一个RDD类里面出现,那么放在第一个迭代器里面,如果在第一个rdd里面出现多次,那么就value就有多个元素,如果没出现那么就是一个空的迭代器,efaultPartitioner(self,other) 一个表示当前分区,一个表示另外一个分区器,

/把key相同的数据搞到同一个分区的同一个组里面,如果是如果是两个RDD,它的value是一个tuple2,
//里面装的的是两个迭代器,如果是三个RDD,则返回的是tuple3,value是对应的是四个迭代器

intersetion:求交集

sc.parallelize(List(1,2,3,4,5))

sc.parallelize(List(1,2,3,4,5),2)

rdd3 = rdd1.intersection(rdd2)

可得交集

 

使用cogroup实现intersection的功能

 

 val conf = new SparkConf().setAppName("ReduceByKey").setMaster("local[*]")

    val sc = new SparkContext(conf)

    val rdd1: RDD[Int] = sc.parallelize(List(1, 2, 3, 4, 5),2)
    val rdd2: RDD[Int] = sc.parallelize(List(4, 5, 6, 7, 8),2)

    //注意迭代器装null,也是一个装null的迭代器,不为空
    /*val rdd3 = rdd1.intersection(rdd2)
    val res = rdd3.collect()
    println(res.toBuffer)
    */
    //使用cogroup实现intersetion的功能
    val rdd3: RDD[(Int, Null)] = rdd1.map((_, null))

    val rdd4: RDD[(Int, Null)] = rdd2.map((_, null))

    val grouped: RDD[(Int, (Iterable[Null], Iterable[Null]))] = rdd3.cogroup(rdd4)
    //对grouped进行过滤
    grouped.filter(t=>(
      t._2._1.nonEmpty
     && t._2._2.nonEmpty
    )
    ).map(_._1)

 

 

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页