数组的不可变数据结构替换

时间:2013-11-02 17:59:33

标签: java functional-programming immutability

当您需要具有最快访问/更新速度的不可变列表时,您会使用什么?如果你必须从中间访问一个元素,LinkedList可能会很慢,而且创建和重新填充它是不可能的。二叉树?四叉树?

2 个答案:

答案 0 :(得分:2)

如果更新很少(或者集合很小),那么在初始化之后你不会写入的数组是值得的。在这些情况下,低得多的常数因子(时间和空间)都超过线性时间更新。

除此之外,还有许多纯功能数据结构为这些情况提供了更好的界限。 2-3个手指树(Haskell的Data.Sequence背后的数据结构)就是一个例子。另一种选择是Clojure的向量和相关的数据结构(例如,轻松的Radix-Balanced Trees),它使用具有高扇出(32或更高)的树来保持读取便宜和结构共享以避免太多副本。

所有这些都是手动实现的中等技巧,特别是如果性能很重要,我不知道现有的实现(我不认为Clojure的向量很容易或从Ja​​va中使用)。

答案 1 :(得分:-1)

我不确定我理解你在寻找什么,但我会尝试根据我在标准课程中看到的一些内容给出一些指示:

  • CopyOnWriteArrayList是一个可变的线程安全列表,因为它在更新时复制了内部数组。也许你可以从中调整一些想法,尽管对于大型列表来说显然效率不高。

  • ConcurrentHashMap在更复杂的结构上实现了类似的想法。它将内部哈希表划分为单独的分区,因此更改只需要锁定对相关分区的访问权限。

    对于不可变列表,您可以执行类似的操作:将列表的内部数组划分为多个分区,并将它们全部视为不可变。当您需要更改列表时,您只需要克隆一个分区和分区的索引,这比复制整个列表要便宜。

  • AWTEventMulticaster实现了类似的目标,但重复了绝对最小值。这是一个聪明的二叉树。请参阅the source

使用较小的内部分区或块,您可以获得更快的更新,但一般来说访问速度较慢。使用更大的块(例如,整个阵列),您的更新速度会变慢,但访问速度会更快。

如果您确实需要最快的访问和更新,则必须使用可变数组。