我学习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'失败,地图将删除一个条目。 –