以下是代码:
val email1 = sc.textFile("/Users/kaiyin/IdeaProjects/learnSpark/src/main/resources/ling-spam/ham/3-378msg3.txt")
val email2 = sc.textFile("/Users/kaiyin/IdeaProjects/learnSpark/src/main/resources/ling-spam/ham/3-378msg4.txt")
val email = email1 ++ email2
println(s"Count check: ${email.count() == email1.count() + email2.count()}")
val partitionLengths = email.aggregate(Vector.empty[Int])((vec, s) => s.length +: vec, (i1, i2) => i1 ++ i2)
println(partitionLengths)
println(partitionLengths.sum == email.map(_.length).sum)
val partitionLengthsMax = email.aggregate(0)((i: Int, s: String) => {
println(s"Partition length: ${s.length}")
i + s.length
}, (i1, i2) => i1.max(i2))
println(partitionLengthsMax)
在repl中运行它会给出:
Count check: true
Vector(244, 0, 31, 96, 0, 23)
true
Partition length: 23
Partition length: 0
Partition length: 96
Partition length: 31
Partition length: 0
Partition length: 244
275
首先,为什么设置为local[4]
时有6个分区?
为什么最大长度不是244?显然275 = 244 + 31.
完整的脚本可以在这里找到:https://github.com/kindlychung/learnSpark/blob/master/src/main/scala/RDDDemo.scala
答案 0 :(得分:0)
为什么设置为本地时有6个分区[4]
请注意,如果rdd1
包含x
个分区,rdd2
包含y
个分区,rdd1 ++ rdd2
将有x+y
个分区。
为什么最大长度不是244?
您似乎认为aggregate
的最后一个参数combOp: (U, U) ⇒ U
仅用于合并单独分区的结果。嗯,事实并非如此:combOp
也用于有效地聚合分区内的结果。
实际上,RDD.aggregate
' implementation几乎如下:
iterator.aggregate(zeroValue)(seqOp, compOb)
来聚合该分区compOb
将所有分区合并到一起在第一步中,aggregate
方法为GenTraversableOnce.aggregate
,ScalaDocs明确指出:
此操作的实现可以在任意数量的集合分区上运行,因此
combop
可以被调用任意次数
底线 - compOp
被称为每RDD分区多次,因此您将看到结果。
答案 1 :(得分:0)
我稍微修改了代码片段以查看中间结果
val partitionLengthsMax = email.aggregate(0)(
(i: Int, s: String) => {
println(s"$i Partition length: ${s.length} ${s.take(15)}")
i + s.length
},
(i1, i2) => {
println(s"$i1, $i2")
i1.max(i2)
})
根据Spark doc。代码段应该意味着获得子分区总和的最大大小。
def aggregate[U](zeroValue: U)(
seqOp: (U, T) ⇒ U,
combOp: (U, U) ⇒ U)(implicit arg0: ClassTag[U]): U
使用给定的组合函数和中性“零值”,聚合每个分区的元素,然后聚合所有分区的结果。此函数可以返回与此RDD,T的类型不同的结果类型U。因此,我们需要一个操作将T合并到U中,并且需要一个操作来合并两个U,如scala.TraversableOnce。允许这两个函数修改并返回它们的第一个参数,而不是创建一个新的U来避免内存分配。