我遇到了将可变集合转换为不可变集合的奇怪行为,这可能会对性能产生重大影响。
让我们看看以下代码:
val map: Map[String, Set[Int]] = createMap()
while (true) {
map.get("existing-key")
}
它只创建一次映射,然后重复访问其中一个enries,其中包含一个值作为值。它可以通过多种方式创建地图:
使用不可变集合:
def createMap() = keys.map(key => key -> (1 to amount).toSet).toMap
或者使用可变集合(请注意最后的两个转换选项):
def createMap() = {
val map = mutable.Map[String, mutable.Set[Int]]()
for (key <- keys) {
val set = map.getOrElseUpdate(key, mutable.Set())
for (i <- 1 to amount) {
set.add(i)
}
}
map.toMap.mapValues(_.toSet) // option #1
map.mapValues(_.toSet).toMap // option #2
}
奇怪的是,可变#1代码创建了一个映射,只要调用toSet
(如果条目存在),就会在其值上调用get
,这可能会导致显着的性能损失(取决于使用情况) - 案例)。
为什么会这样?如何避免这种情况?