我目前的用例非常简单,可变或不可变 Map 都可以解决问题。
有一个采用不可变 Map 的方法,然后调用一个采用不可变 Map 的第 3 方 API 方法
def doFoo(foo: String = "default", params: Map[String, Any] = Map()) {
val newMap =
if(someCondition) params + ("foo" -> foo) else params
api.doSomething(newMap)
}
有问题的 Map 通常很小,最多可能有一个嵌入的案例类实例列表,最多几千个条目。因此,再次假设在这种情况下不可变几乎没有影响(即通过 newMap val 副本基本上具有 Map 的 2 个实例)。
尽管如此,它还是让我有点烦,复制 map 只是为了得到一张新 map ,上面有几个 k->v 条目。
我可以去可变和
params.put("bar", bar)
等我想添加的条目,然后 params.toMap
为 api 调用转换为不可变,这是一个选项。但随后我必须导入并传递可变映射,与使用 Scala 的默认不可变映射相比,这有点麻烦。那么,在不可变 Map 上使用可变 Map 是合理/良好实践的一般准则是什么?
谢谢
编辑
因此,似乎对不可变映射执行添加操作需要几乎恒定的时间,这证实了 @dhg 和 @Nicolas 的断言,即未制作完整副本,这解决了所呈现的具体案例的问题。
最佳答案
根据不可变的 Map 实现,添加一些条目实际上可能不会复制整个原始 Map。这是不可变数据结构方法的优点之一:Scala 会尽量避免复制。
这种行为最容易通过 List
看到。 .如果我有一个 val a = List(1,2,3)
,然后该列表存储在内存中。但是,如果我在前面添加一个附加元素,例如 val b = 0 :: a
,我确实得到了一个新的 4 元素 List
返回,但 Scala 没有复制原始列表 a
.相反,我们只是创建了一个新链接,命名为 b
,并给它一个指向现有列表的指针 a
.
您也可以为其他类型的集合设想这样的策略。例如,如果我向 Map
添加一个元素,集合可以简单地包装现有 map ,在需要时回退到它,同时提供一个 API,就好像它是一个 Map
.
关于Scala 不可变映射,何时变为可变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10141654/