案例场景:原始数据每条为<车牌号,经度,纬度,时间戳,速度>格式的字符串,按照第一个字段车牌号进行分组,即相同车牌号的数据合并到一个列表中。
1. 使用groupBy()算子
//原始数据格式:车牌号,经度,纬度,时间戳,速度
rdd.map(_.split(","))
.groupBy(_ (0))
.map(x => x._2)
2. 使用reduceByKey算子
先将元素转换为ListBuffer(x),然后再在reduceByKey中调用++操作合并列表
rdd.map(_.split(","))
.map(x => (x(0), ListBuffer(x)))
.reduceByKey((list1, list2) => list1 ++ list2)
.map(x => x._2)
3. 使用aggregateByKey算子
调用 aggregateByKey 方法,首先在分区内将相同key的value值追加到同一个ListBuffer 中,然后在分区间用++=操作合并列表
rdd.map(_.split(","))
.map(x => (x(0), x))
.aggregateByKey(ListBuffer[Array[String]]())(
(buffer, value) => buffer += value,
(buffer1, buffer2) => buffer1 ++= buffer2
)
.map(x => x._2)
分析:groupByKey直接进行shuffle操作对所有分区的数据进行分组,数据量大的时候速度较慢。
而reduceByKey、aggregateByKey在shuffle之前会在分区内先进行预聚合,聚合后的数据再进行shuffle,这样一来进行shuffle的数据会变少,速度会快。
reduceByKey、aggregateByKey的区别是前者不同partition以及partition之间的聚合操作是一样的,而后者可以指定两种操作来对应于partition之间和partition内部不同的聚合操作,并且aggregateByKey可以指定初始值。
在aggregateByKey中,如果两种操作是一样的,可以使用foldByKey来代替,并且只传一个操作函数。foldBykey和reudceBykey的区别是前者可以指定一个初始值。