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)