【问题标题】:Conversion of mutable collections to immutable introduces performance penalty可变集合到不可变集合的转换引入了性能损失
【发布时间】:2016-12-05 14:33:48
【问题描述】:

我遇到了关于将可变集合转换为不可变集合的奇怪行为,这可能会显着影响性能。

我们来看看下面的代码:

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 代码创建了一个映射,每当调用get(如果该条目存在)时,它就会在其值上调用toSet,这可能会导致显着的性能损失(取决于用例)。

为什么会这样?如何避免这种情况?

【问题讨论】:

    标签: performance scala collections


    【解决方案1】:

    mapValues 只返回一个地图视图,它将地图的每个键映射到f(this(key))。生成的地图不复制任何元素包裹原始地图。

    查看实现,mapValues 返回一个 MappedValues 的实例,它覆盖了 get function

    def get(key: K) = self.get(key).map(f)
    

    如果你想强制实现地图,请在mapValues 调用之后调用toMap。就像你在 #2 中所做的一样!

    【讨论】:

    猜你喜欢
    • 2012-01-19
    • 2011-03-11
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多