[英]Fastest way to convert IEnumerable<T> to List<T> in C#
在 C# 中,就编写代码所需的时间而言,使用IEnumerable
创建和填充列表的最快方法是什么? 执行所需的时间呢?
我的第一个想法是这样的:
List<int> list = new List<int>();
foreach(int number in iterator)
list.Add(number);
有没有更快的方法?
当谈到List<T>
您基本上有两种方法,我将在下面讨论。 为了清楚起见,假设List<T>
分配需要恒定时间 (C),向List<T>
添加元素也需要恒定时间。
创建空List<T>
并填充它
List<int> list = new List<int>(); // C
foreach(int i in iterator)
{
list.Add(i); //n*C
}
如您所见,此方法需要 n*C + C 时间,因此如果您忽略 C,则复杂度为 O(n)。
基于其他IEnumerable<T>
创建List<T>
IEnumerable<T>
List<int> list = new List<int>(iterator);
但是,迭代器的类型有一个小的区别:
如果迭代器是ICollection<T>
var array = new T[ICollection.Count] // C ICollection.CopyTo(array) // by MSDN O(n)
如果迭代器是IEnumerable<T>
,与创建空并逐项添加相同
因此,如果您分析复杂度,则无法避免 O(n) 复杂度。
但...
List<T>
增长和容量有一个警告可能会影响性能。 默认List<T>
容量为 4,如果您向List<T>
添加超过 4 个元素,则将分配当前大小两倍的新底层数组并复制元素......此过程将重复再次当我们达到List<T>
的容量时。 你可以想象你可能有多少不必要的复制。 为了防止这种情况,最好的选择是提前用容量初始化List<T>
或使用List<T>(ICollection<T>)
构造函数。
// benchmark example
var enumerable = Enumerable.Repeat(1, 1000000);
var collection = enumerable.ToList();
Stopwatch st = Stopwatch.StartNew();
List<int> copy1 = new List<int>(enumerable);
Console.WriteLine(st.ElapsedMilliseconds);
st = Stopwatch.StartNew();
List<int> copy2 = new List<int>(collection);
Console.WriteLine(st.ElapsedMilliseconds);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.