Spark之groupByKey和reduceByKey的区别

1.reduceByKey(func)

功能:

使用func函数合并具有相同键的值

scala编写

复制代码
def main(args: Array[String]): Unit = {
    val sc = new SparkContext(new SparkConf().setAppName("Test3").setMaster("local[*]"))
    val data = Array("one","two","three","two","two","three")
    val arrayRDD: RDD[String] = sc.makeRDD(data)
    val mapRDD: RDD[(String, Int)] = arrayRDD.map(x=>(x,1))
   val data2: RDD[(String, Int)] = mapRDD.reduceByKey(_+_)
    data2.collect().foreach(println)
    sc.stop()
}
复制代码

运行结果:

(two,3)
(one,1)
(three,2)

我们需要留意的事情是,我们调用了reduceByKey操作返回的结果类型是:

org.apache.spark.rdd.RDD[(String, Int)]

注意:这里的collect()方法的作用是收集分布在各个worker的数据到Driver节点

如果不使用这个方法,每个worker的数据只在自己本地显示,并不会在driver节点显示。

2.groupByKey

功能:

对具有相同的key的value进行分组

复制代码
  def main(args: Array[String]): Unit = {
    val sc = new SparkContext(new SparkConf().setAppName("Test3").setMaster("local[*]"))
    val data = Array("one","two","three","two","two","three")
    val arrayRDD: RDD[String] = sc.makeRDD(data)
    val mapRDD: RDD[(String, Int)] = arrayRDD.map(x=>(x,1))
   val data2: RDD[(String, Iterable[Int])] = mapRDD.groupByKey()
    data2.collect().foreach(println)
    sc.stop()
  }
复制代码

我们同样是对跟上面同样的pairRdd进行groupByKey()操作

运行结果:

(two,CompactBuffer(1, 1, 1))
(one,CompactBuffer(1))
(three,CompactBuffer(1, 1))

可以看出,结果并不是把具有相同的key值进行相加,而是就简单的进行了分组,生成一个sequence(序列)。

其实,我们可以把groupByKey()当作reduceByKey(func)操作的一部分,

reduceByKey(func)先是对rdd进行groupByKey()然后在对每个分组进行func操作。

mapRDD.reduceByKey(_+_).collect.foreach(println)
等同于
mapRDD.groupByKey().map(t => (t._1,t._2.sum)).collect.foreach(println)

我们这里通过groupByKey()后调用map遍历每个分组,然后通过t => (t._1,t._2.sum)对每个分组的值进行累加。

因为groupByKey()操作是把具有相同类型的key的值收集到一起聚合成一个集合,集合中有个sum方法,对所有元素进行求和。

注意,(k,v)形式的数据,我们可以通过 ._1,._2 来访问键和值,

用占位符表示就是 _._1,_._2,这里前面的两个下划线的含义是不同的,前边下划线是占位符,后边的是访问方式。

我们记不记得 ._1,._2,._3 是元组的访问方式。我们可以把键值看成二维的元组。

3.reduceByKey(func)和groupByKey()的区别

reduceByKey()对于每个相同的key对应的多个value进行了merge(合并)操作,最重要的是它能够先在本地进行merge操作。merge可以通过func自定义。

groupByKey()也是对每个相同的key对应的多个value进行操作,但是只是汇总生成一个sequence,本身不能自定义函数,只能通过额外通过map(func)来实现。

注意:

使用reduceByKey()的时候,本地的数据先进行merge然后再传输到不同节点再进行merge,最终得到最终结果。

而使用groupByKey()的时候,并不进行本地的merge,全部数据传出,得到全部数据后才会进行聚合成一个sequence,

groupByKey()传输速度明显慢于reduceByKey()。

虽然groupByKey().map(func)也能实现reduceByKey(func)功能,但是,优先使用reduceByKey(func)

 

posted @   Bonnie_ξ  阅读(158)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示