ArrayList与Array和List

我已经编程了很多,最近开始学习更纯粹的计算机科学专题(面试)。

我知道Array和LinkedList数据结构之间的区别,但现在我已经开始使用Java了,我看到了这个ArrayList,我在构思时遇到了麻烦。

网络搜索只是真正告诉我如何使用它们以及什么时候使用它们(每个的好处),但没有什么能回答我的问题:

什么是ArrayList? 我的假设是它是一个列表,它维护对每个元素的内存引用,使它也能像数组一样工作。

我也有一种感觉,因为Java是开放的,我应该能够看看类定义,但还没有弄清楚如何做到这一点。

谢谢!

我喜欢把它想象成一个数据结构,让你享受这两个世界,快速访问索引,如数组和列表的无限增长。 当然,总是需要权衡利弊。

ArrayList实际上是数组的包装器。 每次数组的大小结束时,都会创建一个大小为两倍的新数组,并将原始数组中的所有数据复制到新数组中。

来自java doc:

List接口的可resize的数组实现 。 实现所有可选列表操作,并允许所有元素,包括null。 除了实现List接口之外,此类还提供了一些方法来操作内部用于存储列表的数组的大小。 (这个类大致相当于Vector,除了它是不同步的。) size,isEmpty,get,set,iterator和listIterator操作在恒定时间内运行添加操作以分摊的常量时间运行,即添加n个元素需要O(n)时间 。 所有其他操作都以线性时间运行(粗略地说)。 与LinkedList实现相比,常数因子较低。

每个ArrayList实例都有一个容量。 容量是用于存储列表中元素的数组的大小。 它始终至少与列表大小一样大。 随着元素添加到ArrayList,其容量会自动增加。 除了添加元素具有恒定的摊销时间成本这一事实之外,未指定增长策略的详细信息。

在使用ensureCapacity操作添加大量元素之前,应用程序可以增加ArrayList实例的容量。 这可能会减少增量重新分配的数量。

这允许对大多数操作进行O(1)访问,就像使用数组一样。 有一段时间,您需要使用插入操作来支付此性能,但需要更长时间。

这称为摊销复杂性。 对于那些需要将数组大小加倍的时间,每个操作只需要O(1) 。 在那段时间你会支付O(n)但是如果你在n次操作中平均,那么平均花费的时间只有O(1)而不是O(n)

我们来举个例子:

我们有一个100的数组(n = 100)。 你进行100次插入操作(到不同的索引),每个操作只需要O(1) ,当然所有的索引操作都需要O(1) (因为这是一个数组)。 在101插入时,数组中没有更多容量,因此ArrayList将创建一个新数组,大小为200,将所有值复制到它( O(n)操作),然后插入第101项。 在将数组填充到200个项目之前,所有操作都需要O(1)

ArrayList是由数组直接支持的列表。 更具体地说,它由一个动态resize的数组支持。 您可以在源代码中阅读更多相关内容; 有一些非常好的评论。

这很重要的原因是由于LinkedList的实现方式 – 作为传统的节点集合和对其他节点的引用。 这对索引和遍历有性能影响,而对于ArrayList ,由于它由数组支持,所以需要做的就是索引特定数组以检索值。