【发布时间】:2017-01-30 10:32:46
【问题描述】:
很久以前,我看了一个普林斯顿 Coursera MOOC 的视频讲座:算法介绍,可以在 here 找到。它解释了在添加或删除元素时调整 ArrayList 类似结构的成本。事实证明,如果我们想为我们的数据结构提供调整大小,我们将从O(n) 变为amortized O(n) 以进行add 和remove 操作。
我已经使用 Java ArrayList 好几年了。我一直确信它们会自动增长和收缩。直到最近,令我大吃一惊的是,我在this post 中被证明是错误的。 Java ArrayLists 不会自动收缩(尽管它们当然会增长)。
这是我的问题:
在我看来,在
ArrayLists 中提供收缩不会造成任何伤害,因为性能已经是amortized O(n)。为什么 Java 的创造者没有在设计中包含这个特性?我知道像
HashMaps 这样的其他数据结构也不会自动收缩。 Java中是否还有其他构建在支持自动收缩的数组之上的数据结构?其他语言的趋势是什么?在 Python/C# 中的列表、字典、地图、集合等情况下,自动收缩看起来如何。如果它们与 Java 的做法相反,那么我的问题是:为什么?
【问题讨论】:
-
容器缩小的缺点是,如果添加更多元素,您将不得不再次增长它。仅仅因为您从列表中删除了元素,库不能假设您仍然不需要空间。我不知道像
ArrayList这样会自动缩小的数组包装器,如果发现有人这样做,我会感到非常惊讶。如果您作为ArrayList用户知道您的列表容量现在可以减少,您可以使用trimToSize()。 -
我知道还有更多工作要做,但在
O术语中,如果您提供自动缩小功能,您将失去“任何东西”,就像视频中展示的那样。add和remove的复杂度仍然是amortized O(n) -
顺便说一句,如果有人给
-1,我很乐意阅读建设性反馈。 -
自动增长是必需的以适应更多元素。正如 khelwood 所说,自动收缩不是必需的,如果需要可以手动完成。说“你什么都没有”并不完全正确。您增加了复杂性,并且您无法确定是否需要自动收缩。
-
除非 JDK 开发人员判断
ArrayList操作中的可预测性优于System.arrayCopy中的偶尔打嗝或自定义汇编代码,速度如此之快以至于它会自动调整大小 - 我不能说我看到好处 a) 每次我们调用remove()时支付保证O(N)和 b) 如果/在需要时手动修剪列表,后者尤其令人讨厌。这绝对是一个错误的感觉。冒险猜测一下,我会说他们选择了 a),但老实说,如果您那么关心性能,那么无论如何您都应该直接使用数组。