Spark Rdd之cogroup实现intersection、join、leftOuterJoin、rightOuterJoin

强大算子cogroup

cogroup源码:

// 返回类型 RDD[(K, (Iterable[V], Iterable[W]))]
// 对于this或other中的每个键k,返回一个结果RDD,该RDD包含一个元组,其中包含this和other中该键的Value列表。
def cogroup[W](other: RDD[(K, W)], partitioner: Partitioner): RDD[(K, (Iterable[V], Iterable[W]))] = 
self.withScope {
    if (partitioner.isInstanceOf[HashPartitioner] && keyClass.isArray) {
      throw new SparkException("HashPartitioner cannot partition array keys.")
    }
    val cg = new CoGroupedRDD[K](Seq(self, other), partitioner)
    cg.mapValues { // 对value 进行操作
      case Array(vs, w1s) =>  //vs self的value,w1s other的value
      		(vs.asInstanceOf[Iterable[V]], w1s.asInstanceOf[Iterable[W]]) // 将vs和w1s 实例化为可迭代的(装到compactBuffer里面)
    }
  }

该算子使用的很少,但是他却功能强大,因为它作为底层算子,很多其他我们使用的比较多的算子都是该算子实现的。

  • 在这里插入图片描述

intersection

// 使用cogroup 实现intersection 交集操作
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, 9), 2)

    val cogroupedRdd: RDD[(Int, (Iterable[Null], Iterable[Null]))] = rdd1.map((_, null))
      .cogroup(rdd2.map((_, null)))

    cogroupedRdd.filter{
      case (k,(v1,v2))=>v1.nonEmpty && v2.nonEmpty //偏函数 判断v1不为空,v2也不为空
    }.map(_._1)
      .foreach(println(_))

// 输出:4,5

join

// cogroup 实现 join操作
val rdd1: RDD[(String, Int)] = sc.parallelize(List(("spark", 1), ("hadoop", 1), ("spark", 2), ("hive", 2), ("flink", 2)), 2)
    val rdd2: RDD[(String, Int)] = sc.parallelize(List(("spark", 3), ("hadoop", 4), ("hive", 3)), 2)
    val cogroupedRdd: RDD[(String, (Iterable[Int], Iterable[Int]))] = rdd1.cogroup(rdd2)
    
		cogroupedRdd.flatMapValues(pair => {
      for (i <- pair._1.iterator; j <- pair._2.iterator) // 求笛卡尔积
        yield (i, j)
    }).foreach(println(_))

输出:
(hive,(2,3))
(spark,(1,3))
(spark,(2,3))
(hadoop,(1,4))

leftOuterJoin

val rdd1: RDD[(String, Int)] = sc.parallelize(List(("spark", 1), ("hadoop", 1), ("spark", 2), ("hive", 2), ("flink", 2)), 2)
    val rdd2: RDD[(String, Int)] = sc.parallelize(List(("spark", 3), ("hadoop", 4), ("hive", 3)), 2)

    rdd1.leftOuterJoin(rdd2)
      .foreach(println(_))
    println("--------------------")

    rdd1.cogroup(rdd2)
      .flatMapValues(pair=>{
        if (pair._2.isEmpty) { //默认rdd1 > rdd2
          pair._1.iterator.map((_,None))
        }else{
          for (i<- pair._1.iterator; j<- pair._2.iterator)
            yield (i,Some(j))
        }
      })
      .foreach(println)
输出:
(hive,(2,Some(3)))
(spark,(1,Some(3)))
(spark,(2,Some(3)))
(hadoop,(1,Some(4)))
(flink,(2,None))
--------------------
(hive,(2,Some(3)))
(spark,(1,Some(3)))
(spark,(2,Some(3)))
(hadoop,(1,Some(4)))
(flink,(2,None))

rightOuterJoin

// cogroup 实现rightOuterJoin

val rdd1: RDD[(String, Int)] = sc.parallelize(List(("spark", 1), ("hadoop", 1), ("spark", 2), ("hive", 2), ("flink", 2)), 2)
    val rdd2: RDD[(String, Int)] = sc.parallelize(List(("spark", 3), ("hadoop", 4), ("hive", 3)), 2)

    println("-------rightOuterJoin-----------")
    rdd2.rightOuterJoin(rdd1)
      .foreach(println(_))

    println("-------cogroupRdd-----------")
    val cogroupRdd: RDD[(String, (Iterable[Int], Iterable[Int]))] = rdd2.cogroup(rdd1)
    cogroupRdd.foreach(println(_))

    println("-------resultRdd---------")
    cogroupRdd.flatMapValues(pair => {
      if (pair._1.isEmpty) {
        pair._2.iterator.map((None, _))
      } else {
        for (i <- pair._1.iterator; j <- pair._2.iterator) // 当i,j有一个为null时 ,yield会跳过
          yield (Some(i), j)
      }
    })
      .foreach(println(_))

输出:
-------rightOuterJoin-----------
(hive,(Some(3),2))
(spark,(Some(3),1))
(spark,(Some(3),2))
(hadoop,(Some(4),1))
(flink,(None,2))
-------cogroupRdd-----------
(hive,(CompactBuffer(3),CompactBuffer(2)))
(flink,(CompactBuffer(),CompactBuffer(2)))
(spark,(CompactBuffer(3),CompactBuffer(1, 2)))
(hadoop,(CompactBuffer(4),CompactBuffer(1)))
-------resultRdd---------
(hive,(Some(3),2))
(spark,(Some(3),1))
(spark,(Some(3),2))
(hadoop,(Some(4),1))
(flink,(None,2))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值