哪个更有效率:List<int>还是int[]?

28
有人能告诉我 List<int>int[] 哪个更高效吗?因为我正在开发一个项目,并且你可能知道效率是非常重要的问题。如果您在帖子中添加一些引言注释,那就太好了 :)

10
注意避免过早优化。如果效率在你的应用中很重要,最好编写测试来测量整个功能的性能,而不是集中于微观优化。通常真正的优化需要一个清晰的设计,而微观优化往往会妨碍清晰的设计。 - Andrea Francia
6
一开始使用错误的数据结构会严重影响性能,因此花时间根据需求选择正确的数据结构总是值得的,而不是随意选择一个。 - waterlooalex
6
如果列表不是正确的数据结构,那么数组很可能也不是正确的选择。 - Dour High Arch
这并不是我的经验。当我不需要 List 的可调整大小功能时,我经常使用数组。 - waterlooalex
2
问题实际上是什么时间最重要?你公司真正支付的开发时间,还是代码运行中的一些小时间节省?如果你使用List<int>通过使用自动调整大小来减少编码时间,那就使用它。如果你只需要一个静态大小的数组,请使用int[]。参考280Z28所接受的答案。 - awe
可能是数组与列表的性能比较的重复问题。 - nawfal
6个回答

84
(list should be resizable) ? List<int> : int[]

List<int> 是一个可以根据需要调整大小的 int[] 包装器。使用 JIT 内联,它们应该执行几乎相同,但是 JIT 更容易从 int[] 中获得额外的性能优势,因为它是一个带有专用 IL 指令的 CLI 原始类型。


13

只是为了好玩,我运行了这个:

int cap = 100000;

Stopwatch sw1 = new Stopwatch();
sw1.Start();

int[] ix = new int[cap];
for (int x = 0; x < cap; x++)
{
    ix[x] = 1;
}

sw1.Stop();

Stopwatch sw2 = new Stopwatch();
sw2.Start();
List<int> iy = new List<int>(cap);
for (int y = 0; y < cap; y++)
{
    iy.Add(y);
}
sw2.Stop();

Console.WriteLine(cap.ToString() + "     int[]=" + sw1.ElapsedTicks.ToString());
Console.WriteLine(cap.ToString() + " List<int>=" + sw2.ElapsedTicks.ToString());

Console.ReadKey();

并且得到了以下结果:

100000个int[]=1796542
100000个List=2517922

我用毫秒计时,分别得到了0和1。显然,int[]更快,但除非你处理的是巨大的数组,否则差异微乎其微。


1
如果您在List构造函数中设置了初始容量,就像您为数组所做的那样,我会怀疑性能会更接近。 - Eddie Velasquez
4
他为列表设置了容量。List<int> iy = new List<int>(cap)。根据我的经验,int[] 更快。 - waterlooalex
1
这样的一次测试运行是没有意义的。你需要多次运行测试并平均结果。但是由于类所暗示的方法调用开销,List<int>可能总是较慢。 - orj
5
@orj,怎么可能是“毫无意义”的呢?你说的做法可能更有意义,但它绝不是毫无意义的。这样说话太苛刻了,也不准确。另外,你认为我在发表回复之前运行了多少次才得出结果?不只是一次,所得到的结果都很典型。虽然我没有对它们进行平均,但似乎没有必要进行一个“完整的”基准测试。 - Cyberherbalist
1
尝试使用引用类型而不是值类型再次尝试。我怀疑你在这里遇到的最大性能问题来自于将int装箱和拆箱为列表。 - overstood
5
整型不会进行装箱/拆箱。如果泛型参数 T 是值类型,那么 T[] 将是一个值类型的数组,而不是一个装箱后的值类型数组。 - Lou

10
如果您确切知道集合中将包含多少个元素,并且不需要任何额外的 List<int> 功能,而且(这是一个非常严肃的 AND性能是一个严重问题,那么请使用 int[]。否则,请使用 List<int>

3
当使用T[]时,List<T>的大多数特性都可以作为Array类的静态成员使用。如果列表是固定大小的,请使用T[],因为两者都实现了IList<T>接口。 - Sam Harwell

7

后者更有效。
在源代码中,List<>被一些数组命名。
例如,List<Type> aa=new List<Type>();
通常情况下,声明一个 array Type[],它的长度是一个确定的数字。 换句话说,如果你声明了一个 List<>,一个大空间已经被使用了。
如果 List<> 的元素超出了长度,那么数组应该被复制到另一个更大的数组中。 因此,最好不要使用 List<>
更好的方法是声明其长度。
List<Type> aa=new List<Type>(10);


3
你的英文可能不太好,但这并不是让你的回答被评分降低的理由。在这个网站上有一些不友善的人存在,如果他们不能理解你的写作,那么他们应该让它保持未评分状态。我出于好意帮你提高了分数。祝和平。 - Cyberherbalist
1
我认为人们不会因为英语不好而掉队。正如其他几个答案所指出的那样,只有当您拥有数十万条记录时,性能差异才是显著的。对于许多目的来说,List<>在合理的成本范围内为您提供更多的功能。仅在您拥有1e6或更多条目,并且您确切地知道有多少条目,性能真正是一个问题时,您才应该将其优化为数组。这个答案被投票否决(并不是我投的,要知道),因为它给出了一个绝对的建议,而许多人(如果不是大多数的话,在我看来)都会受到其建议的影响。 - Michael Blackburn

6

List内部使用数组,因此正确使用数组始终更有效率(或至少一样有效率)。


谢谢您的简短回答...清晰、简洁。不需要再说什么了。 - steve
1
@steve 当然可以,除了问题中特别要求的解释性评论。 - Michael Blackburn
亲爱的布莱克本先生:请您不要发表讽刺性的评论,因为这里不适合这样的言论。此外,这个问题显然并没有具体要求解释。也许您认为“介绍性说明”部分是在要求解释,但我认为那是无意义的,应该被忽略。最后,我认为这是一个非常好的回答(尽管得票很少),但可悲的是,您的评论削弱了这个回答的价值。 - steve

4
如果您打算使用列表提供的任何功能(搜索、排序、删除、调整大小),那么我建议您选择使用列表,因为这些功能很可能已经被高度优化,并且您不太可能编写出更好的版本。

2
List<T>.Sort 只是在内部数据数组上调用 Array.Sort<T>,这对于任何数组都可用。搜索也是一样。List<T> 唯一真正提供的是自动调整大小和 ForEach(),但我想 T[] 的枚举器甚至更快,因为它不必检查数组是否已更改。 - Sam Harwell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接