6

我在 c# 中工作,我正在创建一个列表(newList),我可以从另一个列表(otherList)的长度中获取它。在 c# 中,列表的实现方式是使用 otherList.Count 或只使用 newList.Add(obj) 而不担心长度来预先分配列表的长度以提高性能?

4

4 回答 4

12

实现以下构造函数List<T>的目的是为了提高像您这样的场景中的性能:

http://msdn.microsoft.com/en-us/library/dw8e0z9z.aspx

public List(int capacity)

只需在构造函数中传递容量。

newList = new List<string>(otherList.Count);

于 2013-10-07T16:11:09.597 回答
4

如果您知道新列表的确切长度,那么使用该容量创建它确实会执行 - 有点 - 更好。

原因是List<T>内部的实现使用了数组。如果它变得太小,则会创建一个新数组,并将旧数组中的项目复制到新项目中。

于 2013-10-07T16:11:26.523 回答
4

取自MSDN上的备注部分

a的容量是 可以容纳List<T>的元素的数量。List<T>当元素添加到 aList<T>时,容量会根据需要通过重新分配内部数组自动增加。

如果可以估计集合的大小,那么指定初始容量就无需在向List<T>.

可以通过调用 TrimExcess 方法或显式设置容量属性来减少容量。减少容量会重新分配内存并复制List<T>.

因此,如果您估计要填充的列表的大小,这将表明性能会有所提高。当然,另一方面是分配的列表太大,因此不必要地占用了内存。

老实说,除非我真的需要,否则我不会担心这种微优化。

于 2013-10-07T16:12:55.243 回答
-1

所以我对预分配的场景进行了基准测试,只是想分享一些数字。代码只是把这个时间:

var repetitions = 100000000
var list = new List<object>();
for (var i = 0; i < repetitions; i++)
    list.Add(new object());

比较是通过在列表中分配确切的重复次数,两倍的数量并且没有预分配。这是时代:

  • 未预先分配的列表:6561、6394、6556、6283、6466
  • 预分配列表:5951、6037、5885、6044、5996
  • 列出双重预分配:6710、6665、6729、6760、6624

那么预分配值得吗?是的,如果列表中的对象数量已知,或者该数量的底线已知(列表中至少有多少项目)。

如果不是这样,您实际上可能会浪费更多的时间和内存,因为预分配将使用时间和内存来为所需的分配腾出空间。

请注意,同样在内存方面,精确的预分配是最节省内存的,因为不进行预分配会使您的列表增长超过所需的最紧容量。

于 2019-07-26T12:33:50.630 回答