Scala 不可变映射,如具有 constant/effective 常量查找的数据结构

Scala immutable Map like datastructure that has constant/effective constant lookup

在为 Scala 设计 JSON AST 时,我们意识到我们遇到了一个问题(可以在此处更详细地描述 https://github.com/json4s/json4s-ast/issues/8),理想情况下我们希望表示 JObject(JSON 对象)的 Map 结构要么保留其键的顺序,要么使用具有恒定或有效恒定查找时间的默认 Ordering 按键排序。

我们需要保留顺序或保证键排序的东西的原因是,当有人序列化 JValue 时,我们需要确保它始终输出相同的 JSON JValue(最明显的情况是缓存 JValue 序列化)

问题是 Scala stdlib 似乎没有不可变的 Map 之类的数据结构,该数据结构 preserves/orders 按键查找时间为 O(c) 或 O(eC)(参考 http://docs.scala-lang.org/overviews/collections/performance-characteristics.html )

有谁知道在 Scala 集合库之后的某个地方是否有这种数据结构的实现(或者即使这种数据结构通常存在)?

一般情况下你不能在常数时间内排序,所以使用Ordering是正确的。

而且据我所知,实际上并没有任何不可变的数据结构可以让你在任意位置添加和删除并保持稳定的性能(你能得到的最好的是 O(log N) 尽管有些人喜欢假装如果对数的底数足够大,则为 "effectively constant").

所以你要求的是不可能的。

但作为后备方案,TreeMap 对于排序键来说也不错。 O(log N) 解决方案非常有效。

对于顺序正确的键,您通常需要维护三个映射:索引到键、键到索引和键到值。键的索引应该是 TreeMap 这样你就可以按顺序走。其他的可以随便。基本思想是,当你想添加一个键值对时,你递增索引并将 (index -> key) 添加到第一个映射并将 (key -> index) 添加到第二个映射。然后当你按顺序走时,你沿着索引到键的映射走,并在键值映射中查找。当您按键删除时,您会找到具有键到索引映射的索引,因此您也可以从索引到键映射中删除它。

经过与其他人的深思熟虑,我们似乎将维护 2 个数据结构(一个向量和一个映射,即 https://github.com/json4s/json4s-ast/issues/8#issuecomment-125025604),这基本上就是@Aivean 提到的。性能比潜在的内存使用更受关注。

如果你需要排序,TreeMap确实是最快的结构,它确实有 O(log(n)),没有排序你有标准的不可变 Map,这是 O( n(log(n))(Haskell 也有 Data.Map,其工作方式类似)。

感谢您的回答!