简体   繁体   English

转换 IEnumerable 的最快方法<T>列出<T>在 C# 中

[英]Fastest way to convert IEnumerable<T> to List<T> in C#

In C#, what is the fastest way to create and fill a List using an IEnumerable in terms of time required to write the code for?在 C# 中,就编写代码所需的时间而言,使用IEnumerable创建和填充列表的最快方法是什么? What about in terms of time required to execute?执行所需的时间呢?

My first thought was this:我的第一个想法是这样的:

List<int> list = new List<int>();

foreach(int number in iterator)
    list.Add(number);

Is there a faster way?有没有更快的方法?

When it comes to List<T> essentially you have 2 approaches, which I am trying to discuss below.当谈到List<T>您基本上有两种方法,我将在下面讨论。 For the sake of clarity lets assume, allocation of the List<T> takes constant time (C), adding an element to the List<T> also takes constant time.为了清楚起见,假设List<T>分配需要恒定时间 (C),向List<T>添加元素也需要恒定时间。


Create empty List<T> and populate it创建空List<T>并填充它

List<int> list = new List<int>(); // C
foreach(int i in iterator)
{
    list.Add(i); //n*C
}

as you can see this approach takes n*C + C time, so if you neglect the C the complexity is O(n).如您所见,此方法需要 n*C + C 时间,因此如果您忽略 C,则复杂度为 O(n)。


Create List<T> based on the other IEnumerable<T>基于其他IEnumerable<T>创建List<T> IEnumerable<T>

List<int> list = new List<int>(iterator);

however, there is a small difference regards the type of iterator:但是,迭代器的类型有一个小的区别:

  1. if the iterator is ICollection<T>如果迭代器是ICollection<T>

    var array = new T[ICollection.Count] // C ICollection.CopyTo(array) // by MSDN O(n) var array = new T[ICollection.Count] // C ICollection.CopyTo(array) // by MSDN O(n)

  2. if the iterator is IEnumerable<T> , the same as creating empty and add item by item如果迭代器是IEnumerable<T> ,与创建空并逐项添加相同

So, if you analyze the complexity you cannot avoid O(n) complexity.因此,如果您分析复杂度,则无法避免 O(n) 复杂度。

BUT...但...

There is one caveat with the List<T> growth and capacity which might impact performances. List<T>增长和容量有一个警告可能会影响性能。 The default List<T> capacity is 4 and if you add more than 4 elements to the List<T> the new underlying array, twice of the current size, will be allocated and the elements will be copied...this process will repeat again when we reach the capacity of the List<T> .默认List<T>容量为 4,如果您向List<T>添加超过 4 个元素,则将分配当前大小两倍的新底层数组并复制元素......此过程将重复再次当我们达到List<T>的容量时。 You can imagine how much unnecessary copying you might have.你可以想象你可能有多少不必要的复制。 In order to prevent this, the best option is to initialize List<T> with capacity in advance or use the List<T>(ICollection<T>) ctor.为了防止这种情况,最好的选择是提前用容量初始化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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM