哪个更好?array,ArrayList或List <T>(在性能和速度方面)

use*_*509 18 c# arrays performance list arraylist

我需要快速处理我的页面.要添加的值的计数将是动态的.

以上哪一个是首选?支持有正当理由.

编辑:例如:

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

要么,

ArrayList al = new ArrayList();
al.Add(str.Split(','));
Run Code Online (Sandbox Code Playgroud)

Joe*_*Joe 20

List<T> 通常应该优先考虑 ArrayList

  • 更快的价值类型,因为它避免拳击.
  • 强类型元素

如果你想你暴露给调用者名单是不可改变的,这是由双方支持List<T>ArrayList:

List<T>.AsReadOnly()
ArrayList.ReadOnly(ArrayList list);
Run Code Online (Sandbox Code Playgroud)

你的问题要求在ArrayList和之间进行选择List<T>,但是你的例子显示了一个数组,但两者都没有.


Ser*_*-Tm 17

用于"不可变"集合的数组, List<T>用于可变集合.

  • "永恒的"收藏 - 仅在创作时改变,后来许多阅读.
  • 可变收集 - 许多变化的所有时间

性能统计(阵列与列表与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
Run Code Online (Sandbox Code Playgroud)

源代码:

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);
    }
  }
Run Code Online (Sandbox Code Playgroud)

  • 除了数组不是真正不可变的,`IEnumerable <T>`或`IReadOnlyList <T>`(.Net 4.5中的新内容)是. (7认同)
  • 数组是可变的,在需要不变性时应该避免使用:http://blogs.msdn.com/b/ericlippert/archive/2008/09/22/arrays-considered-somewhat-harmful.aspx (5认同)
  • 数组不是不可变的.而是使用`ReadOnlyCollection <T>`来绕过一个`List <T>`的不可变包装器 - 通常通过调用`List <T> .AsReadOnly()`. (4认同)
  • @DarkGray,事实是,Array不是不可变的,也就是说,可以在创建后修改它(例如`myArray [i] = newValue`).至于性能,您的统计数据毫无意义,因为它们没有显示他们如何进行测量.固定大小(即不能添加/删除元素)与不可变(这意味着现有元素也不能替换)不同. (2认同)
  • 其中一些测试存在缺陷.例如,您的Generate function for Array使用事先知道其大小的事实.但是你没有在List生成中做类似的事情(例如使用`List <T>`构造函数中的Capacity参数). (2认同)

Tho*_*and 6

List <T> 总是会比arrayList快.List <T>'s不必包含添加到它们的值.

ArrayList 只有"接受"对象,这意味着虽然你可以将任何你想要的对象添加到列表中,但它必须被装箱(由CLR隐式地),然后当你需要时它必须再次取消装箱(由你明确地)价值.

编辑:这是一个很好的链接

  • 装箱差异仅适用于值类型.对于参考类型,两者将是相等的. (8认同)