【问题标题】:How is List<T> internally mapped?List<T> 如何在内部映射?
【发布时间】:2012-08-04 09:45:52
【问题描述】:

它是在内部被视为数组还是被 CLR 视为完全不同的类型?

我正在尝试在列表中实现整数值。

List<int> lst = new List<int>();
lst.Add(3);
lst.Add(4);

对比

我创建了一个整数数组

int[] arr = new int[2];
arr[0] = 3;
arr[1] = 4;

数组返回更好的时间跨度结果。那么为什么人们更喜欢 List.

【问题讨论】:

  • 你可以试试ILSpy 自己看看。拥有动态可增长/可收缩列表的原因是它不像Array 那样是固定大小的。

标签: .net arrays list generics clr


【解决方案1】:

List&lt;&gt; 是一种数据结构的实现,它负责按需分配内存;它允许在任何索引处插入和删除等。因此它比简单的数组方便得多。

在底层,当前的List&lt;&gt; 实现使用数组进行存储,执行类似数组的操作时的开销很小。增加的便利通常值得一点(如果有的话)性能差异。添加项目通常更快,因为列表分配内存块并且不需要在每次添加时进行新的分配和复制(与纯数组相比,其中Length 始终绑定到内存中的大小)。

【讨论】:

  • 那么,您的意思是,尽管可以忽略不计,List&lt;&gt; 的响应速度会比Array 慢,就速度 而言?
  • 当然。 List 是对数组的抽象,抽象会花费额外的 CPU 周期。但是,我同意 Lucero 的观点,在正常情况下,List 已经足够快了。
  • “响应时间”通常是无关紧要的,请求在(快速且廉价的)边界检查后传递到底层数组。这甚至可能被运行时内联,因此它甚至不需要额外的调用。
【解决方案2】:

一个普通的随机访问列表通常有一个内部数组。 .NET List&lt;T&gt; 实现就是这样做的。其他实现,例如 LinkedList&lt;T&gt; 使用带有引用的元素链而不是数组。更奇特的列表可能会在内部使用树进行排序。

List&lt;T&gt; 中的内部数组被初始化为一个较短的长度(我相信是 4),如果您尝试在数组的最大边界之外添加,它会被扩展。由于这可能很耗时(需要复制数组),因此数组的大小会增加一倍,即当您添加第 5 个元素时,内部数组的大小会调整为 8,依此类推。

【讨论】:

  • 我记得读过,List&lt;&gt; 数据结构针对速度进行了优化,而Array DS 针对内存进行了优化。您似乎与 List&lt;&gt; 针对 Speed 进行了优化这一事实相矛盾。 (当我们说它被重新调整大小和重新分配时,当超出界限时)
  • 我不同意这种区别。 List 内部有一个数组,因此本质上与数组存储方式没有什么不同。您为列表支付了微小的性能损失,并且为此您获得了动态/可调整大小的集合。所以总而言之,列表和数组之间最大的区别是,您始终可以将内容添加到列表中。
  • @bugbuster,如果你想将一个项目添加到一个数组中(以便Length 增加,也就是说,不仅仅是更改一个现有项目),你必须也重新分配数组。该列表将增长为更大的块并跟踪数组中已使用元素的数量,因此顺序添加速度更快。
猜你喜欢
  • 1970-01-01
  • 2016-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多