创建一个新数组,排除一个项目比创建一个列表并删除它更快?

Creating a new array, discluding an item is faster than creating a list and removing it?

我拼命想找到一种更快的方法来创建一个数组,其中没有一个项目,而不是创建这些对象的列表并删除该项目。

原因是我的数组平均有 5 个项目,大多数时候更少,并且创建一个列表只是为了删除一个我不再想要的项目,对我来说似乎太多了。

自从我前段时间编写了自己的探查器后,我决定将该方法和我想到的另一个方法进行测试,结果很重要。

int[] a1 = new int[] { 1, 2, 3 };

方法 1(创建对象列表并删除第二项):

 Profiler.Start("Method 1");
 List<int> a2 = new List<int>(a1);
 a2.RemoveAt(1);
 Profiler.Stop("Method 1");

方法2(创建一个大小相同但为1的数组,并排除第2项):

 Profiler.Start("Method 2");
 int[] a3 = new int[a1.Length - 1];
 int l = 0;
 for (int i = 0; i < a1.Length; i++) if (a1[i] != 2) { a3[l] = a1[i]; l++; }
 Profiler.Stop("Method 2");

探查器结果:

http://i.stack.imgur.com/al8i6.png

问题 为什么性能差异如此显着?

我从来没有真正花时间研究数组和列表之间的区别。

似乎开销来自列表内容的初始化,而不是来自对 List.RemoveAt() 的调用。

换句话说,List<int> a2 = new List<int>(a1);行占了时间

这里有一些代码试图消除 List.RemoveAt()Array.Copy() 所花费的时间。

在我的 PC 上发布版本的结果是:

LIST Elapsed: 00:00:00.4724841
ARRAY Elapsed: 00:00:00.4670488
LIST Elapsed: 00:00:00.4714016
ARRAY Elapsed: 00:00:00.4675552
LIST Elapsed: 00:00:00.4703538
ARRAY Elapsed: 00:00:00.4698310

这表明时间非常相似。

测试程序为:

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Demo
{
    public static class Program
    {
        public static void Main()
        {
            int[] a1 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };

            int trials = 3;
            int iterations = 10000000;

            Stopwatch sw = new Stopwatch();

            for (int i = 0; i < trials; ++i)
            {
                for (int j = 0; j < iterations; ++j)
                {
                    List<int> a2 = new List<int>(a1);

                    sw.Start();
                    a2.RemoveAt(1);
                    sw.Stop();
                }

                Console.WriteLine("LIST Elapsed: " + sw.Elapsed);
                sw.Reset();

                for (int j = 0; j < iterations; ++j)
                {
                    int[] a3 = new int[a1.Length - 1];
                    int l = 0;

                    sw.Start();

                    for (int k = 0; k < a1.Length; k++)
                    {
                        if (a1[k] != 2)
                        {
                            a3[l] = a1[k];
                            l++;
                        }
                    }

                    sw.Stop();
                }

                Console.WriteLine("ARRAY Elapsed: " + sw.Elapsed);
                sw.Reset();
            }
        }
    }
}