你的例子可以做得更簡單,因爲fol低點:
> fruits.groupBy(identity).mapValues(_.size)
res176: Map[String, Int] = Map("mango" -> 1, "orange" -> 2, "apple" -> 3)
但是,如果您想並行化並使用MapReduce模式,那麼reduce就很有用。如果你不併行化,你只需要依次減少列表(1,1,1,1 ...)。比較:
> List(1,1,1,1,1,1,1).reduce{(a,b) => println(s"$a+$b=${a+b}"); a + b}
1+1=2
2+1=3
3+1=4
4+1=5
5+1=6
6+1=7
res187: Int = 7
與並行版本(注意par
法):
> List(1,1,1,1,1,1,1).par.reduce{(a,b) => println(s"$a+$b=${a+b}"); a + b}
1+1=2
1+1=2
1+2=3
1+1=2
2+2=4
3+4=7
res188: Int = 7
您可以通過定義常用reduceByKey
功能按如下方式使用你的情況的MapReduce模式:
implicit class MapReduceTraversable[T, N](val traversable: Traversable[(T, N)]) {
def reduceByKey(f: (N, N) => N) = traversable.par.groupBy(_._1).mapValues(_.map(_._2)).mapValues(_.reduce(f))
}
val fruits = List("apple", "apple", "orange", "apple", "mango", "orange", "apple", "apple", "apple", "apple")
fruits.map(f => (f,1)).reduceByKey(_ + _)
res2: collection.parallel.ParMap[String, Int] = ParMap(orange -> 2, mango -> 1, apple -> 7)
您可以像以前一樣調試它:
fruits.map(f => (f,1)).reduceByKey{(a,b) => println(s"$a+$b=${a+b}"); a + b}
1+1=2
1+1=2
2+1=3
3+1=4
4+1=5
5+1=6
6+1=7
res9: Map[String, Int] = Map("mango" -> 1, "orange" -> 2, "apple" -> 7)
有一個'reduce',但'foldLeft'在這種情況下更合適,因爲'reduce'不接受默認值,所以它會在空列表上失敗。 –
如果我們使用reduce而不是功能如何? – user2841047
我剛剛提出這個問題。在目前的狀態下,它需要改進它的措辭...但我仍然認爲這個問題有一定的教學價值,並且對中級/初級階梯用戶很有用 – jayunit100