我对C#中的列表进行了一些速度测试。这是我无法解释的结果。我希望有人能弄清楚发生了什么。
如果在cloneList.Add(next)之前调用cloneList.RemoveAt(cloneList.Count - 1),则1000次迭代的毫秒数:x毫秒。
如果在cloneList.Add(next)之前没有调用cloneList.RemoveAt(cloneList.Count - 1),则1000次迭代的毫秒数:至少 20x 毫秒。
似乎还有一个语句,我的代码得到的速度提高了20倍(参见下面的代码):
Stopwatch stopWatch = new Stopwatch();
Random random = new Random(100);
TimeSpan caseOneTimeSpan = new TimeSpan();
TimeSpan caseTwoTimeSpan = new TimeSpan();
int len = 1000;
List<int> myList = new List<int>();
myList.Capacity = len + 1;
// filling the list
for (int i = 0; i < len; i++)
myList.Add(random.Next(1000));
// number of tests (1000)
for (int i = 0; i < 1000; i++)
{
List<int> cloneList = myList.ToList();
int next = random.Next();
// case 1 - remove last item before adding the new item
stopWatch.Start();
cloneList.RemoveAt(cloneList.Count - 1);
cloneList.Add(next);
caseOneTimeSpan += stopWatch.Elapsed;
// reset stopwatch and clone list
stopWatch.Reset();
cloneList = myList.ToList();
// case 2 - add without removing
stopWatch.Start();
cloneList.Add(next);
caseTwoTimeSpan += stopWatch.Elapsed;
stopWatch.Reset();
}
Console.WriteLine("Case 1: " + caseOneTimeSpan.TotalMilliseconds);
Console.WriteLine("Case 2: " + caseTwoTimeSpan.TotalMilliseconds);
Console.WriteLine("Case 2 / Case 1: " + caseTwoTimeSpan.TotalMilliseconds / caseOneTimeSpan.TotalMilliseconds);
答案 0 :(得分:3)
将项目添加到列表时,有两种可能性:
虽然大多数Add
调用将是O(1),但有些调用是O(n)。
删除最后一项始终是O(1)。
由于Add
有时取决于列表的大小,因此当列表较大时,它需要更长的时间(如果任何调用需要新的缓冲区)。如果在添加新项目时始终删除项目,则确保内部缓冲区始终具有足够的空间。
您可以查看Capacity
的{{1}}属性,查看内部缓冲区的当前大小,并将其与List
进行比较,Count
是列表实际具有的项目数。 (因此Capacity-Count
是缓冲区中空闲项的数量。)虽然在实际程序中不常用,但在调试或开发应用程序时查看这些工具对于帮助您了解下面发生的事情非常有用。
答案 1 :(得分:0)
这应该会消除差异:
// reset stopwatch and clone list
stopWatch.Reset();
cloneList = myList.ToList();
cloneList.Capacity = cloneList.Capacity + 1; // add this
// case 2 - add without removing
stopWatch.Start();
cloneList.Add(next);
caseTwoTimeSpan += stopWatch.Elapsed;