.NET 数据结构:
更多关于为什么 ArrayList 和 List 实际上不同的对话
数组
正如一位用户所说,数组是“老派”集合(是的,数组被认为是一个集合,尽管不是 的一部分System.Collections
)。但是,与其他集合相比,数组的“老派”是什么,即您在标题中列出的那些(这里是 ArrayList 和 List(Of T))?让我们从数组的基础开始。
首先, Microsoft .NET 中的数组是“允许您将多个 [逻辑相关] 项视为单个集合的机制”(请参阅链接文章)。这意味着什么?数组按顺序存储各个成员(元素),一个接一个地存储在内存中,并具有起始地址。通过使用数组,我们可以轻松地访问从该地址开始的顺序存储的元素。
除此之外,与编程 101 个常见概念相反,数组确实可以非常复杂:
数组可以是单维的、多维的或加法的(交错的数组值得一读)。数组本身不是动态的:一旦初始化,一个n大小的数组就会保留足够的空间来容纳n个对象。数组中的元素数量不能增加或减少。Dim _array As Int32() = New Int32(100)
在内存块上为数组保留足够的空间以包含 100 个 Int32 原始类型对象(在这种情况下,数组被初始化为包含 0)。该块的地址返回到_array
。
根据这篇文章,公共语言规范(CLS) 要求所有数组都是从零开始的。.NET 中的数组支持非从零开始的数组;但是,这种情况不太常见。由于零基数组的“共性”,微软花了很多时间优化它们的性能;因此,单维、从零开始的 (SZ) 数组是“特殊的”——并且实际上是数组的最佳实现(与多维等相反)——因为 SZ 具有用于操作它们的特定中间语言指令。
数组总是通过引用传递(作为内存地址)——这是数组难题的一个重要部分。虽然他们进行边界检查(会抛出错误),但也可以在数组上禁用边界检查。
同样,数组的最大障碍是它们无法重新调整大小。它们具有“固定”容量。在我们的历史中介绍 ArrayList 和 List(Of T):
ArrayList - 非泛型列表
ArrayList(连同——尽管这里List(Of T)
有一些关键的区别,稍后解释)——也许最好被认为是集合的下一个补充(在广义上)。ArrayList 继承自IList('ICollection' 的后代)接口。ArrayLists 本身比 Lists更庞大- 需要更多开销。
IList
确实使实现能够将 ArrayLists 视为固定大小的列表(如 Arrays);然而,除了 ArrayLists 添加的额外功能之外,使用固定大小的 ArrayLists 并没有真正的优势,因为在这种情况下 ArrayLists(相对于 Arrays)明显更慢。
根据我的阅读,ArrayLists 不能是锯齿状的:“不支持使用多维数组作为元素......”。再一次,ArrayLists 棺材上的另一个钉子。ArrayLists 也不是“类型化的”——这意味着,在一切之下,ArrayList 只是一个动态的对象数组:Object[]
. 这在实现 ArrayList 时需要大量装箱(隐式)和拆箱(显式),再次增加了它们的开销。
未经证实的想法:我想我记得我读过或听过我的一位教授说 ArrayList 是试图从 Arrays 转移到 List 类型 Collections 的混蛋概念孩子,即曾经对 Arrays 进行了很大改进,它们不再是最好的选择,因为已经对收藏进行了进一步的开发
List(Of T):ArrayList 变成了什么(并希望变成什么)
内存使用量的差异足以让 List(Of Int32) 消耗的内存比包含相同原始类型的 ArrayList 少 56%(在上述绅士的链接演示中为 8 MB 对 19 MB:再次,链接在这里) - 虽然这是 64 位机器的复杂结果。这种差异确实表明了两件事:第一(1),装箱的 Int32 类型“对象”(ArrayList)比纯 Int32 原始类型(List)大得多;第二 (2),由于 64 位机器的内部工作,差异是指数级的。
那么,有什么区别,什么是List(Of T)?MSDN将 a 定义List(Of T)
为“……一个可以通过索引访问的强类型对象列表”。这里的重要性是“强类型”位: List(Of T) '识别'类型并将对象存储为它们的类型。因此, anInt32
存储为 anInt32
而不是Object
类型。这消除了装箱和拆箱引起的问题。
MSDN 指定这种差异仅在存储原始类型而不是引用类型时发挥作用。同样,差异确实发生在大规模上:超过 500 个元素。更有趣的是,MSDN 文档中写道:“使用 List(Of T) 类的特定于类型的实现而不是使用 ArrayList 类对您有利......”
本质上,List(Of T) 是 ArrayList,但更好。它是 ArrayList 的“通用等价物”。像 ArrayList 一样,在排序之前不能保证排序(见图)。List(Of T) 还具有一些附加功能。