保留插入顺序的不可变 Scala Map 实现

Posted

技术标签:

【中文标题】保留插入顺序的不可变 Scala Map 实现【英文标题】:Immutable Scala Map implementation that preserves insertion order [duplicate] 【发布时间】:2012-03-08 00:05:24 【问题描述】:

LinkedHashMap 用于保留映射中的插入顺序,但这仅适用于可变映射。保留插入顺序的不可变 Map 实现是哪个?

【问题讨论】:

这不是完全重复的,问题是不可变映射,所谓的重复是关于可变和不可变的。另一个问题没有直接回答不可变的部分(也许是间接的) 【参考方案1】:

ListMap 使用基于列表的数据结构实现不可变映射,因此保留了插入顺序。

scala> import collection.immutable.ListMap
import collection.immutable.ListMap

scala> ListMap(1 -> 2) + (3 -> 4)
res31: scala.collection.immutable.ListMap[Int,Int] = Map(1 -> 2, 3 -> 4)

scala> res31 + (6 -> 9)
res32: scala.collection.immutable.ListMap[Int,Int] = Map(1 -> 2, 3 -> 4, 6 -> 9)

以下扩展方法 - Seq#toListMap 在使用 ListMaps 时非常有用。

scala> import scalaz._, Scalaz._, Liskov._
import scalaz._
import Scalaz._
import Liskov._

scala> :paste
// Entering paste mode (ctrl-D to finish)

implicit def seqW[A](xs: Seq[A]) = new SeqW(xs)
class SeqW[A](xs: Seq[A]) 
  def toListMap[B, C](implicit ev: A <~< (B, C)): ListMap[B, C] = 
    ListMap(co[Seq, A, (B, C)](ev)(xs) : _*)  
  



// Exiting paste mode, now interpreting.

seqW: [A](xs: Seq[A])SeqW[A]
defined class SeqW

scala> Seq((2, 4), (11, 89)).toListMap
res33: scala.collection.immutable.ListMap[Int,Int] = Map(2 -> 4, 11 -> 89)

【讨论】:

ListMap 有一个陷阱 - 使用现有键调用 update() 更改 项目的顺序。示例:ListMap("a" → 1, "b" → 2).updated("a", 2).toList 产生 List((b,2), (a,2))。对我的用例来说非常不幸:(【参考方案2】:

虽然ListMap 会保留插入顺序,但效率不是很高 - 例如查找时间是线性的。我建议您创建一个包含immutable.HashMapimmutable.TreeMap 的新集合类。不可变映射应参数化为immutable.HashMap[Key, (Value, Long)],其中元组中的Long 为您提供指向TreeMap[Long, Key] 中相应条目的指针。然后你在旁边放一个入口柜台。此树形图将根据插入顺序对条目进行排序。

您以直接的方式实现插入和查找 - 递增计数器,插入哈希映射并将计数器键对插入树形映射。您使用哈希映射进行查找。

您使用树形图实现迭代。

要实现remove,你必须从hash map中移除key-value对,并使用tuple中的index从tree map中移除对应的entry。

【讨论】:

+1。在不久的将来有没有机会在 stdlib 中有这样的集合? 您愿意详细说明原因吗? 因为当您从向量中删除元素时,您存储在元组中的索引会随着时间而改变。这是为什么存在具有不同权衡的不同集合的完美示例。与经典的 Linked-List 映射相比,您的实现失去了在恒定时间内删除键的能力(最多 log n)。 当然。我已经编辑了我的答案。 阅读关于 TreeMap 的部分答案,使用 Long 反映元素插入时间的键。如果您的比较器在插入顺序上,则树将保留插入顺序。

以上是关于保留插入顺序的不可变 Scala Map 实现的主要内容,如果未能解决你的问题,请参考以下文章

快学Scala第13章----集合

Scala之Map,Tuple

scala 数据结构(七 ):集 Set

Scala 中不可变集实现的性能

使用Scala中的不可变值查找路径是不是存在于图形中

Scala 可变map与不可变map互转