插入新绑定时是否复制了整个Map?

时间:2012-04-03 23:30:56

标签: haskell

我想更好地了解例如实习生。 Data.Map。当我在Map中插入一个新的绑定时,由于数据的不变性,我得到一个与旧数据结构加上新绑定相同的新数据结构。

我想了解这是如何实现的。编译器是否最终通过复制整个数据结构来实现这一点。数以百万计的绑定?通常可以说可变数据结构/数组(例如Data.Judy)或命令式编程语言在这种情况下表现更好吗?在字典/键值存储方面,不可变数据是否有任何优势?

3 个答案:

答案 0 :(得分:31)

Map建立在树数据结构之上。基本上,构造了一个新的Map ,但它几乎完全被指向结构的指针填充。由于Haskell中的值永远不会改变,因此这是一种安全且非常重要的优化,称为 sharing

这意味着您可以使用相同数据结构的许多相似版本,但只有不同树的分支将被重新存储;其余的只是指向分支原始副本的指针。当然,如果你丢弃旧的Map,你所做的更改的分支将由垃圾收集器回收。

共享是不可变数据结构性能的关键。您可能会发现this Wikipedia article有帮助;它有一些启发性图表,显示修改后的数据如何通过共享来表示。

答案 1 :(得分:15)

没有。 The documentation for Data.Map.insert表示插入需要 O(log n)时间。如果它必须复制整个结构,就不可能满足那个界限。

答案 2 :(得分:5)

Data.Map不会复制旧地图;它(懒惰地)分配O(log N)个新节点,这些节点指向(并因此共享)大部分旧地图。

由于“更新”地图不会破坏旧版本,因此这种数据结构可让您更自由地构建并发算法。