轉(zhuǎn)載請(qǐng)注明出處:http://www.reibang.com/p/15739e95a46e
@貳拾貳畫生
最近在學(xué)習(xí)spark,理解這兩個(gè)函數(shù)時(shí)候費(fèi)了一些勁,現(xiàn)在記錄一下禾锤。
1. rdd.fold(value)(func)
說到fold()
函數(shù)蛔屹,就不得不提一下reduce()
函數(shù)茂卦,他倆的區(qū)別就在于一個(gè)初始值青团。
reduce()
函數(shù)是這樣寫的:
rdd.reduce(func)
參數(shù)是一個(gè)函數(shù)譬巫,這個(gè)函數(shù)的對(duì)rdd中的所有數(shù)據(jù)進(jìn)行某種操作,比如:
val l = List(1,2,3,4)
l.reduce((x, y) => x + y)
對(duì)于這個(gè)x
督笆,它代指的是返回值芦昔,而y
是對(duì)rdd各元素的遍歷。
意思是對(duì) l
中的數(shù)據(jù)進(jìn)行累加娃肿。
flod()
函數(shù)相比reduce()
加了一個(gè)初始值參數(shù):
rdd.fold(value)(func)
scala的語法確實(shí)是比較奇怪的咕缎,既然有兩個(gè)參數(shù),你就不能把兩個(gè)參數(shù)放在一個(gè)括號(hào)里嗎料扰?也是醉了凭豪,這種寫法確實(shí)容易讓人迷惑。
val l = List(1,2,3,4)
l.fold(0)((x, y) => x + y)
這個(gè)計(jì)算其實(shí) 0 + 1 + 2 + 3 + 4
记罚,而reduce()
的計(jì)算是:1 + 2 + 3 + 4
墅诡,沒有初始值,或者說rdd的第一個(gè)元素值是它的初始值桐智。
2. rdd.aggregate(value)(seqOp, combOp)
剛才說到reduce()
和fold()
末早,這兩個(gè)函數(shù)有一個(gè)問題,那就是它們的返回值必須與rdd的數(shù)據(jù)類型相同说庭,啥意思呢然磷?比如剛才那個(gè)例子,l
的數(shù)據(jù)是Int
刊驴,那么reduce()
和flod()
返回的也必須是Int
姿搜。
aggregate()
函數(shù)就打破了這個(gè)限制。比如我返回(Int, Int)
捆憎。這很有用舅柜,比如我要計(jì)算平均值的時(shí)候。
要算平均值躲惰,我就有兩個(gè)值是要求的致份,一個(gè)是rdd的各元素的累加和,另一個(gè)是元素計(jì)數(shù)础拨,我初始化為(0, 0)
氮块。
那么就是:
val l = List(1,2,3,4)
l.aggregate(0, 0)(seqOp, combOp)
那么seqOp
和combOp
怎么寫呢?而combOp又是啥意思呢诡宗?
我們將seqOp寫為:
(x, y) => (x._1 + y, x._2 + 1)
這啥意思滔蝉?
在講到reduce()
函數(shù)的時(shí)候我說:
val l = List(1,2,3,4)
l.reduce((x, y) => x + y)
對(duì)于這個(gè)x
,它代指的是返回值塔沃,而y
是對(duì)rdd各元素的遍歷蝠引。
在aggregate()
這也一樣,x
不是返回值嗎,我返回值是(Int, Int)
啊立肘,它有兩個(gè)元素啊边坤,我可以用x._1
和x._2
來代指這兩個(gè)元素的名扛,y
不是rdd的元素遍歷嗎谅年,那我x._1 + y
就是各個(gè)元素的累加和啊,x._2 + 1
就是元素計(jì)數(shù)啊肮韧。遍歷完成后返回的(Int, Int)
就是累加和和元素計(jì)數(shù)啊融蹂。
按理說有這么一個(gè)函數(shù)就應(yīng)該結(jié)束了,后邊那個(gè)combOp
是干嘛的弄企?
因?yàn)槲覀兊挠?jì)算是分布式計(jì)算超燃,這個(gè)函數(shù)是將累加器進(jìn)行合并的。
例如第一個(gè)節(jié)點(diǎn)遍歷1和2, 返回的是(3, 2)
拘领,第二個(gè)節(jié)點(diǎn)遍歷3和4, 返回的是(7, 2)
意乓,那么將它們合并的話就是3 + 7, 2 + 2
,用程序?qū)懢褪?/p>
(x, y) => (x._1 + y._1, x._2 + y._2)
最后程序是這樣的:
val l = List(1,2,3,4)
r = l.aggregate(0, 0)((x, y) => (x._1 + y, x._2 + 1), (x, y) => (x._1 + y._1, x._2 + y._2))
m = r._1 / r._2.toFload
m
就是所要求的均值约素。