使用数组或 List<> 哪个更好? [复制]

Posted

技术标签:

【中文标题】使用数组或 List<> 哪个更好? [复制]【英文标题】:Which is better to use array or List<>? [duplicate] 【发布时间】:2011-02-27 20:38:00 【问题描述】:

我想知道哪种类型的性能更好,您认为应该使用哪种类型。

例如,我有一个字符串列表,不知道我需要多少项,因此使用 .Add(String) 函数非常方便。我可以随时轻松地将新字符串添加到列表中。

使用每种方法的优点/缺点是什么?

列表是新的数组吗?

【问题讨论】:

@Evan:您评论的第二部分极具误导性。您可以使用与数组相同的方式初始化具有特定容量的List&lt;T&gt;。如果您事先知道尺寸,那么您使用哪一个都没有关系,如果您事先不知道尺寸正如问题明确指出的那样,那么您真的可以t 使用数组。如果您有证据表明数组提供“更好”的读取性能,请发布带有该证据的答案。 【参考方案1】:

List&lt;String&gt; 使用数组String[] 实现。

如果您不知道您将拥有多少个元素,请使用List&lt;String&gt;

您可以在容量构造函数参数 (new List&lt;String&gt;(10)) 中给出您期望的估计(或最大)元素数量,这将是基础数组的初始大小。

当您Add() 一个项目并且该项目没有空间时,底层数组将被复制到一个大小为两倍的新数组中。

我做什么:当我知道集合的确切大小并且我知道我不会更改集合的大小时,我会使用一个数组 (String[])。否则我使用List&lt;String&gt;

顺便说一句,这适用于任何类型,而不仅仅是String

【讨论】:

+1。用于提及列表初始容量。 同上。良好的“现实世界”理由 +1 是最好的答案,但它只是比较差异的一半。 [阅读性能] 对于数组,如果索引可以立即检索到值,因为偏移量是静态的,而对于列表,需要爬取项目以获得索引的值。对于大型集合,这可能会对性能产生巨大影响。 [写入性能] 相反,列表可以无限增长而无需移动数据。使用数组,您需要分配一个新数组并将内存复制到其中(确实效率低下)。内存流是不断增长的数组的答案。 @Evan:您似乎认为List&lt;T&gt; 是作为链表实现的。也许你应该做你的研究,或者甚至只是阅读你投票的答案,因为这一行的第一行清楚地表明(准确)List&lt;T&gt; 是使用数组实现的,当列表需要增长时,这些数组会被复制到新数组中.如果你想要一个链表,你可以使用LinkedList&lt;T&gt; 类。【参考方案2】:

这取决于使用场景,但它也是一个微优化,直到您通过分析确定瓶颈。使用最适合使用的任何内容。

【讨论】:

【参考方案3】:

如果您不知道要添加的项目的大小,请始终选择List&lt;string&gt;,而不是字符串数组。

【讨论】:

【参考方案4】:

如果您需要动态调整大小,请使用List&lt;string&gt;

如果您担心性能,那么我建议您从List&lt;string&gt; 开始,看看是否真的存在问题。它在内部使用数组,所以我认为,在大多数情况下,应该没有性能问题。

如果你有一个静态大小的集合,你仍然可以使用string[]

【讨论】:

【参考方案5】:

当然这取决于您的应用程序,但在某些情况下List&lt;string&gt;(或者甚至只是IEnumerable&lt;string&gt; 更可取。

【讨论】:

【参考方案6】:

在大多数情况下使用 List,不必担心性能。您很有可能会经历整个职业生涯,而无需通过将 List 转换为数组来调整性能。

【讨论】:

【参考方案7】:

在大多数情况下,性能差异并不明显,因此我会使用 List&lt;string&gt;,因为它提供了更多功能,可能在不同情况下有用。

【讨论】:

【参考方案8】:

确实需要更多上下文才能正确回答问题:

公共 API 中,您应该尝试使用抽象集合类型,以便以后可以根据需要更改内部实现。

如果集合不应被外界更改,请使用IEnumerable&lt;T&gt;。 如果集合被外界改变,请使用ICollection&lt;T&gt;。 如果需要索引访问,请使用IList&lt;T&gt;

私有实现中,使用抽象类型并不那么重要:

如果您需要索引访问并知道最终大小,请使用T[]List&lt;T&gt;。 如果您需要索引访问但不知道最终大小,请使用List&lt;T&gt;。 如果您计划以 LIFO 模式访问元素,请使用 Stack&lt;T&gt;。 如果您计划以 FIFO 模式访问元素,请使用 Queue&lt;T&gt;。 如果您需要访问列表开头和结尾的元素,而不是中间的元素,请使用LinkedList&lt;T&gt;。 如果您不想重复,请使用HashSet&lt;T&gt;

在 .NET 4.0 中,您有更多选择,但这些都是基础。

【讨论】:

“如果集合不应该被外界改变,请使用 IEnumerable”——我不同意这种描述。如果返回值引用的对象是可变列表,则返回 IEnumerable 将无济于事 - 调用者始终可以强制转换。如果调用者只能枚举,则应返回 IEnumerable,如果还需要 Count,则应返回 ICollection,如果需要索引访问,则应返回 IList。在上述所有种情况下,如果集合不应被外界更改,请将其包装在只读集合中(例如,使用 List.AsReadOnly)。 @Joe:我不喜欢这种说法。调用者总是可以尝试将 anything 你给它的 anything else - 这样做只是糟糕的设计。如果需要,您可以将所有结果包装在 ReadOnlyCollection&lt;T&gt; 中,但这并不能保护您免受 敌对 调用者的侵害;他们可以只使用反射来获取内部可变列表。如果这是超安全代码,那么保证这个特定不变量的唯一方法是返回一个 new,生成 IEnumerable&lt;T&gt; 实例,即返回 originalEnumerable.Select(x =&gt; x).ToArray() 但无论如何,这些建议是从可发现性和代码维护的角度(编写自记录代码),而不是安全角度;如果您属于后者,那么您还有 许多 其他事情需要担心。这也是我使用短语“不应该”而不是“不得”的原因——这不是保证,只是一个非常强烈的暗示。如果尝试修改,ReadOnlyCollection&lt;T&gt; 将给出 runtime 错误;您希望尽可能在编译时捕获此类错误。 @Evan:没有相关的性能特征,因为正如brickner 的回答正确指出的那样,List&lt;T&gt; 类是使用一个数组来实现的。至于给出不好的建议-您甚至在什么时候阅读了答案的前半部分,其中我明确指出最好使用抽象类型,特别是使用完成这项工作所需功能最少的类型?最后,至于“将它放在一个属性中”,这个答案或我在这个网站上的任何答案都没有说明应该直接访问一个字段,我也猜不出你为什么会推断出来。 我的错......我也不确定我在想什么。当我睡眠不足时,应该远离 ***。出于某种原因,我认为 List 等同于 LinkedList 并且错过了关于在可公开访问的部分上使用接口代替类的部分。在面对之后(出于好奇),我在 Google 上搜索了 List 与 T[] 的性能,显然读取访问的权衡是

以上是关于使用数组或 List<> 哪个更好? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

哪个是基于数据库值在C#突出显示列表框中将字符串传递给List的更好方法

在性能 Lambda 或简单循环方面哪个更好? [复制]

哪个更好,单 for 循环或双 for 循环迭代二维数组? C++

哪个是指定 HTML 固定列宽(宽度或样式属性)的更好方法

Array 与 List<T>:何时使用哪个?

哪个是创建圆形按钮的更好方法:<img> 或 background-image? [复制]