RDD算子其他的都比较好理解,唯独fold和agg这俩稍微比较难理解一点,因为scala语言这个语法个人感觉有点异于其他语言。
先说说reduce()函数,他和fold()函数也就一个初始值的区别:
val rdd=list1.parallelize(List(1,2,3,4))
rdd.reduce((x,y)=>x+y)
其实就是 1+2+3+4 返回10 ,x其实指代的就是返回值,y是对rdd元素的遍历。意思是对 l
中的数据进行累加。
对与fold()函数来说:
rdd.fold(0)((x,y)=>x+y)
这个计算其实 0 + 1 + 2 + 3 + 4.
reduce()
和fold()返回值的数据类型必须和rdd是一样的。aggregate()
函数就打破了这个限制。比如我返回(Int, Int)
。
2. rdd.aggregate(value)(seqOp, combOp)
要算平均值,我就有两个值是要求的,一个是rdd的各元素的累加和,另一个是元素计数,我初始化为(0, 0)
。
rdd.aggregate(0, 0)(seqOp, combOp)
seqOp是:(x, y) => (x._1 + y, x._2 + 1)
对于这个x
,它代指的是返回值,而y
是对rdd各元素的遍历。
在aggregate()
这也一样,x
不是返回值吗,我返回值是(Int, Int)
啊,它有两个元素啊,我可以用x._1
和x._2
来代指这两个元素的,y
不是rdd的元素遍历吗,那我x._1 + y
就是各个元素的累加和啊,x._2 + 1
就是元素计数啊。遍历完成后返回的(Int, Int)
就是累加和和元素计数啊。
按理说有这么一个函数就应该结束了,后边那个combOp
是干嘛的?
因为我们的计算是分布式计算,这个函数是将累加器进行合并的。
例如第一个节点遍历1和2, 返回的是(3, 2)
,第二个节点遍历3和4, 返回的是(7, 2)
,那么将它们合并的话就是3 + 7, 2 + 2
,用程序写就是
(x, y) => (x._1 + y._1, x._2 + y._2)
r = rdd.aggregate(0, 0)(
(acc, value) => (acc._1 + value, acc._2 + 1),
(acc1, acc2) => (acc1._1 + acc2._1, acc1._2 + acc2._2)
)
m = r._1 / r._2.toFload