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

旧街凉风 提交于 2020-01-03 04:51:14

问题


In C#, what is the fastest way to create and fill a List using an IEnumberable in terms of time required to write the code for? 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?


回答1:


When it comes to List<T> essentially you have 2 approaches, which I am trying to discuss below. 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.


Create empty List<T> and populate it

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).


Create List<T> based on the other 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>

    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

So, if you analyze the complexity you cannot avoid O(n) complexity.

BUT...

There is one caveat with the List<T> growth and capacity which might impact performances. 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>. 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.

// 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);


来源:https://stackoverflow.com/questions/54298050/fastest-way-to-convert-ienumerablet-to-listt-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!