我學習Scala從書「斯卡拉不耐煩」工作的練習。請參閱以下問題以及我的答案和代碼。我想知道我的答案是否正確。此外代碼不起作用(所有頻率都是1)。錯誤在哪裏?Scala的並行頻率計算不起作用
Q10:哈利黑客讀取文件到字符串並希望使用 並行採集同時更新上線的 部分信件的頻率。他使用以下代碼:
val frequencies = new scala.collection.mutable.HashMap[Char, Int] for (c <- str.par) frequencies(c) = frequencies.getOrElse(c, 0) + 1
爲什麼這是一個可怕的想法?他怎樣才能真正平行計算 ?
我的回答: 這不是一個好主意,因爲如果2個線程同時更新相同的頻率,結果是不確定的。
我的代碼:
def parFrequency(str: String) = {
str.par.aggregate(Map[Char, Int]())((m, c) => { m + (c -> (m.getOrElse(c, 0) + 1)) }, _ ++ _)
}
單元測試:
"Method parFrequency" should "return the frequency of each character in a string" in {
val freq = parFrequency("harry hacker")
freq should have size 8
freq('h') should be(2) // fails
freq('a') should be(2)
freq('r') should be(3)
freq('y') should be(1)
freq(' ') should be(1)
freq('c') should be(1)
freq('k') should be(1)
freq('e') should be(1)
}
編輯: 閱讀this線後,我更新的代碼。現在,如果單獨運行測試,但如果作爲套件運行則失敗。
def parFrequency(str: String) = {
val freq = ImmutableHashMap[Char, Int]()
str.par.aggregate(freq)((_, c) => ImmutableHashMap(c -> 1), (m1, m2) => m1.merged(m2)({
case ((k, v1), (_, v2)) => (k, v1 + v2)
}))
}
編輯2: 見下面我的解決方案。
「現在測試如果獨立運行,但如果作爲套件運行則失敗。」它以什麼方式失敗? –
@Paul'freq應該有大小8'失敗,地圖將刪除一個條目。 –