直译过来是 按照 Key 进行聚合
源码如下:
说明:
第一个参数是, 给每一个分区中的每一种key一个初始值
第二个是个函数, Seq Function, 这个函数就是用来先对每个分区内的数据按照 key 分别进行定义进行函数定义的操作
第三个是个函数, Combiner Function, 对经过 Seq Function 处理过的数据按照 key 分别进行进行函数定义的操作
也可以自定义分区器, 分区器有默认值
整个流程就是:
在 kv 对的 RDD 中,按 key 将 value 进行分组合并,合并时,将每个 value 和初始值作为 seq 函数的参数,进行计算,返回的结果作为一个新的 kv 对,然后再将结果按照 key 进行合并,最后将每个分组的 value 传递给 combine 函数进行计算(先将前两个 value 进行计算,将返回结果和下一个 value 传给 combine 函数,以此类推),将 key 与计算结果作为一个新的 kv 对输出
示例:
1. 创建一个多分区的 RDD
-
scala> val rdd = sc.parallelize(List((
"a",1),(
"a",2),(
"a",3),(
"b",4),(
"b",5),(
"c",6)),3)
-
rdd: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[108] at parallelize at <console>:24
2. 查看分区情况
-
scala> rdd.glom.collect
-
res175:
Array[
Array[(
String,
Int)]] =
Array(
Array((a,
1), (a,
2)),
Array((a,
3), (b,
4)),
Array((b,
5), (c,
6)))
3. 进行聚合
-
scala> val res = rdd.
aggregateByKey(
0)(math.
max(_,_),_+_)
-
res: org.
apache.
spark.
rdd.
RDD[(
String,
Int)] =
ShuffledRDD[
109] at aggregateByKey at <
console>:
26
4. 查看结果
-
scala> res.collect
-
res171:
Array[(
String,
Int)] =
Array((c,
6), (a,
5), (b,
9))
示例说明:
聚合是 ByKey 的, 计算针对 value, 所以不看 key
第一个函数 math.max(_+_):
按照 key 在分区内聚合第一次
0 作为初始值, 使用 math.max 函数迭代每一个分区中的所有元组的 value 值进行比较, 注意是按照分区, 所以算出的结果就是每一个分区中每个 key 都筛选出一个最大值, 有多少个 key 就有多少个元组, 组成集合. 比如第一个分区中, 有 (a, 1) (a, 2), 那么筛选的结果就是一个 (a, 2)
第二个函数 _+_:
按照 key 在分区间聚合第二次
还是根据 key 值, 将 key 相同的 value 全部相加, 最后得到结果