相同点:
1,都作用于 RDD[K,V]
2,都是根据key来分组聚合
3, 默认,分区的数量都是不变的,但是都可以通过参数来指定分区数量
不同点:
1, groupByKey默认没有聚合函数,得到的返回值类型是RDD[ k,Iterable[V]]
2, reduceByKey 必须传聚合函数 得到的返回值类型 RDD[(K,聚合后的V)]
3, groupByKey().map() = reduceByKey
最重要的区别:
reduceByKey 会进行分区内聚合,然后再进行网络传输
groupByKey 不会进行局部聚合
结论:
如果这两个算子,都可以使用, 优先使用reduceByKey
具体代码如下:
import org.apache.spark.rdd.RDD
import org.apache.spark.{Partitioner, SparkConf, SparkContext}
/**
* @author WangLeiKai
* 2018/9/18 16:19
*/
object ReduceByKeyDemo {
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setAppName("ReduceByClass")
conf.setMaster("local[*]")//设置为本地运行
//设置程序的入口
val sc: SparkContext = new SparkContext(conf)
//创建RDD
val rdd1: RDD[Int] = sc.makeRDD(List(1,2,3,4,5))
//调用groupBy方法
val groupedRdd1: RDD[(String, Iterable[Int])] = rdd1.groupBy(t => t.toString)
val rdd2: RDD[(String, Int)] = sc.makeRDD(List(("rb", 1000), ("baby", 990),
("yangmi", 980), ("bingbing", 5000), ("bingbing", 1000), ("baby", 2000)), 3)
val groupByKeyRDD2: RDD[(String, Iterable[Int])] = rdd2.groupByKey(2)
val groupByKeyRDD1: RDD[(String, Iterable[Int])] = rdd2.groupByKey()
//调用groupByKey + mapValues 就相当于 reduceByKey方法
val result: RDD[(String, Int)] = groupByKeyRDD1.mapValues(_.sum)
val reduceByKeyRDD: RDD[(String, Int)] = rdd2.reduceByKey(_+_)
val rdd6: RDD[(String, Int)] = rdd2.reduceByKey(_ + _)
// 指定生成的rdd的分区的数量
val rdd7: RDD[(String, Int)] = rdd2.reduceByKey(_ + _, 10)
val rdd5: RDD[(String, List[Int])] = sc.makeRDD(List(("a", List(1, 3)), ("b", List(2, 4))))
rdd5.reduceByKey(_ ++ _)
sc.stop()
}
}
注意:如果想查看执行结果的话,可以调用foreachPartition(println)方法,然后再toString(foreachPartition(println)是RDD的Action类的算子,可以直接看到返回结果)