22

I require a fast speed in processing my page. The count of the values to be added will be dynamic.

Which one of the above is preferred? Support with a valid reason.

Edit: For eg:

string str = "a,b,c"; //Count of the number of elements in str is not fixed
string[] arr = str.Split(',');

or,

ArrayList al = new ArrayList();
al.Add(str.Split(','));
Serj-Tm
  • 16,581
  • 4
  • 54
  • 61
user1509
  • 1,151
  • 5
  • 17
  • 45
  • 9
    Why not try it for yourself? Besides, it all depends on what you want to do with the Array, ArrayList or List. I'd pick the one that's easiest to work with and only worry about performance when you actually need it. – Kristof Claes May 30 '12 at 11:41
  • try out each in your particular situation, profile and see which one best serves your need. They each serve different purposes. There isn't a generic 'this is best' answer that fits all situations. – Sam Holder May 30 '12 at 11:41
  • 28
    I love the smell of [premature-optimization] in the morning. – Jamiec May 30 '12 at 11:41
  • 2
    `List` and `ArrayList` use arrays for their backing storage. They can be as fast as arrays (and they are) but they cannot be faster. – Sergey Kalinichenko May 30 '12 at 11:44
  • 1
    similar to http://stackoverflow.com/questions/128636/net-data-structures-arraylist-list-hashtable-dictionary-sortedlist-sorted/128754#128754 – Tilak May 30 '12 at 11:55

3 Answers3

25

List<T> should generally be preferred over ArrayList

  • faster for value types as it avoids boxing.
  • strongly typed elements

If you want lists you expose to callers to be immutable, this is supported by both List<T> and ArrayList:

List<T>.AsReadOnly()
ArrayList.ReadOnly(ArrayList list);

Your question asks about choosing between ArrayList and List<T>, but your example shows an array, which is neither.

Joe
  • 122,218
  • 32
  • 205
  • 338
20

Array for "immutable" collections, List<T> for mutable collections.

  • "Immutable" collection - changed on creation only, and many reading later.
  • Mutable collection - many changes all time

Performance stats (Array vs List vs ReadonlyCollection):

       Array                List        ReadOnlyCollection         Penalties      Method
00:00:01.3932446    00:00:01.6677450    00:00:06.2444633    1 vs  1,2  vs  4,5   Generate
00:00:00.1856069    00:00:01.0291365    00:00:02.0674881    1 vs  5,5  vs 11,1   Sum
00:00:00.4350745    00:00:00.9422126    00:00:04.5994937    1 vs  2,2  vs 10,6   BlockCopy
00:00:00.2029309    00:00:00.4272936    00:00:02.2941122    1 vs  2,1  vs 11,3   Sort

Source code:

interface IMethods<T>
{
  T Generate(int size, Func<int, int> generator);
   int Sum(T items);
   T BlockCopy(T items);
   T Sort(T items);
}

class ArrayMethods:IMethods<int[]>
{
  public int[] Generate(int size, Func<int, int> generator)
  {
    var items = new int[size];
    for (var i = 0; i < items.Length; ++i)
      items[i] = generator(i);
    return items;
  }
  public int Sum(int[] items)
  {
    int sum = 0;
    foreach (var item in items)
      sum += item;
    return sum;
  }
  public int[] BlockCopy(int[] items)
  {
    var res = new int[items.Length / 2];
    Buffer.BlockCopy(items, items.Length / 4 * sizeof(int), res, 0, res.Length * sizeof(int));
    return res;
  }
  public int[] Sort(int[] items)
  {
    var res = new int[items.Length];
    Buffer.BlockCopy(items, 0, res, 0, items.Length * sizeof(int));
    return res;
  }
}
class ListMethods : IMethods<List<int>>
{
  public List<int> Generate(int size, Func<int, int> generator)
  {
    var items = new List<int>(size);
    for (var i = 0; i < size; ++i)
      items.Add(generator(i));
    return items;
  }
  public int Sum(List<int> items)
  {
    int sum = 0;
    foreach (var item in items)
      sum += item;
    return sum;
  }
  public List<int> BlockCopy(List<int> items)
  {
    var count = items.Count / 2;
    var res = new List<int>(count);
    var start = items.Count / 4;
    for (var i = 0; i < count; ++i)
      res.Add(items[start + i]);
    return res;
  }
  public List<int> Sort(List<int> items)
  {
    var res = new List<int>(items);
    res.Sort();
    return res;
  }
}
class ReadOnlyCollectionMethods:IMethods<ReadOnlyCollection<int>>
{
  public ReadOnlyCollection<int> Generate(int size, Func<int, int> generator)
  {
    return new ReadOnlyCollection<int>(Enumerable.Range(0, size).Select(generator).ToList());
  }

  public int Sum(ReadOnlyCollection<int> items)
  {
    int sum = 0;
    foreach (var item in items)
      sum += item;
    return sum;
  }


  public ReadOnlyCollection<int> BlockCopy(ReadOnlyCollection<int> items)
  {
    return new ReadOnlyCollection<int>(items.Skip(items.Count / 4).Take(items.Count / 2).ToArray());
  }
  public ReadOnlyCollection<int> Sort(ReadOnlyCollection<int> items)
  {
    return new ReadOnlyCollection<int>(items.OrderBy(s => s).ToList());
  }
}

static class Program
{
  static Tuple<string, TimeSpan>[] CheckPerformance<T>(IMethods<T> methods) where T:class
  {
    var stats = new List<Tuple<string, TimeSpan>>();

    T source = null;
    foreach (var info in new[] 
      { 
        new {Name = "Generate", Method = new Func<T, T>(items => methods.Generate(10000000, i => i % 2 == 0 ? -i : i))}, 
        new {Name = "Sum", Method =  new Func<T, T>(items => {Console.WriteLine(methods.Sum(items));return items;})}, 
        new {Name = "BlockCopy", Method = new Func<T, T>(items => methods.BlockCopy(items))}, 
        new {Name = "Sort", Method = new Func<T, T>(items => methods.BlockCopy(items))}, 
        new {Name = "Sum", Method =  new Func<T, T>(items => {Console.WriteLine(methods.Sum(items));return items;})}, 
      }
     )
    {
      int count = 10;
      var stopwatch = new Stopwatch();
      stopwatch.Start();
      T res = null;
      for (var i = 0; i < count; ++i)
        res = info.Method(source);
      stopwatch.Stop();
      source = res;
      stats.Add(new Tuple<string, TimeSpan>(info.Name, stopwatch.Elapsed));
    }
    return stats.ToArray();
  }

  static void Main()
  {
    var arrayStats = CheckPerformance(new ArrayMethods());
    var listStats = CheckPerformance(new ListMethods());
    var rcStats = CheckPerformance(new ReadOnlyCollectionMethods());

    Console.WriteLine("       Array                List        ReadOnlyCollection         Penalties      Method");
    for(var i = 0; i < arrayStats.Length; ++i)
    {
      Console.WriteLine("{0}    {1}    {2}    1 vs {3,4:f1}  vs {4,4:f1}   {5}", arrayStats[i].Item2, listStats[i].Item2, rcStats[i].Item2, 
        listStats[i].Item2.TotalSeconds / arrayStats[i].Item2.TotalSeconds,
        rcStats[i].Item2.TotalSeconds / arrayStats[i].Item2.TotalSeconds, arrayStats[i].Item1);
    }
  }
Serj-Tm
  • 16,581
  • 4
  • 54
  • 61
  • 7
    Except array is not really immutable, `IEnumerable` or `IReadOnlyList` (new in .Net 4.5) is. – svick May 30 '12 at 11:42
  • @svick Array for fast and immutable solution is better than nothing. – Serj-Tm May 30 '12 at 11:44
  • 5
    Array is not immutable. Instead use `ReadOnlyCollection` for an immutable wrapper round a `List` - usually by calling `List.AsReadOnly()`. – Joe May 30 '12 at 11:48
  • 6
    Arrays are mutable, and should be avoided when immutability is needed: http://blogs.msdn.com/b/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx – Joshua May 30 '12 at 11:55
  • What does immutable and mutable mean? Please explain. – user1509 May 30 '12 at 12:59
  • 2
    @DarkGray, the fact is, Array is not immutable, that is, it is possible to modify it after creation (e.g. `myArray[i] = newValue`). As for performance, your statistics are meaningless as they don't show how they're doing the measurements. Being fixed-size (i.e. can't add/remove elements) is not the same as immutable (which means existing elements can't be replaced either). – Joe May 30 '12 at 14:05
  • 2
    Some of those tests are flawed. For example, your Generate function for Array uses the fact that its size is known in advance. But you don't do something similar in your List generation (e.g. use the Capacity argument in the `List` constructor). – Joe May 30 '12 at 14:28
  • Another example of a flawed test is that the "block copy" of a read only structure doesn't need to even copy the data, it can reference the original data since the original can't change. – Servy May 30 '12 at 14:50
9

List <T> is always gonna be faster than an arrayList. List <T>'s dont have to box the values that are added to them.

ArrayList only "accept" objects, so that means that while you can add any object you want to the list, it will have to be boxed (implicitly by the CLR) and then it has to be unboxed again (explicitly by you) when you need the values.

edit: here is a nice link

omikes
  • 8,064
  • 8
  • 37
  • 50
Thousand
  • 6,562
  • 3
  • 38
  • 46
  • 10
    The boxing difference only applies to value types. For reference types the two will be equal. – Servy May 30 '12 at 14:05