哪个更快:清除收集或实例化新的

我的代码中有一些通用列表,有几十个或几百个元素。 有时我需要用其他对象重新填充这个列表,所以问题是:调用Clear()方法或创build一个new List<T>()会更快?

什么会更快,调用Clear()方法或创build一个新的List()?

这是不可能回答的。 这取决于很多因素,包括收集时间的长短。

这里最好的select是:

  1. 剖析应用程序,看看这个真的很重要。 它可能不会有任何明显的区别,在这种情况下,我会使用最有意义的方法,就如何看待这个对象。

  2. 如果确实如此,写两组代码,并测量速度差(如果有的话)。

从实际的angular度来看,调用Clear()实际上并不会减less内存(由List<T>本身使用),因为它不会缩小列表的容量,只会消除其中包含的值。 创build一个新的List<T>会导致一个新的列表被分配,这将导致更多的分配和增长。 然而,这并不意味着它会变慢 – 在许多情况下,重新分配将会更快,因为您不太可能将大arrays提升到更高的垃圾收集世代,从而可以保持GC过程更快。 如果不知道自己的确切情况并在分析器中进行测量,则无法知道您的scheme中哪一个更好。

我已经运行了这个testing:

 using System; using System.Collections.Generic; using System.Linq; using System.Diagnostics; namespace TestSpeed { public class Program { static void Main(string[] args) { int defaultN = 1000; Stopwatch sw = new Stopwatch(); while (true) { Console.WriteLine("Enter test elements number:"); int n; if (!int.TryParse(Console.ReadLine(), out n)) n = defaultN; else defaultN = n; Console.WriteLine("Test with {0} elements", n); List<object> list = Enumerable.Repeat(new object(), n).ToList(); sw.Start(); Clear(list); sw.Stop(); Console.WriteLine("Clear: {0} ms", sw.ElapsedTicks / 10000D); GC.Collect(); GC.WaitForPendingFinalizers(); List<object> list2 = Enumerable.Repeat(new object(), n).ToList(); sw.Restart(); Reinitialize(list2); sw.Stop(); Console.WriteLine("Reinitialize: {0} ms", sw.ElapsedTicks / 10000D); GC.Collect(); GC.WaitForPendingFinalizers(); List<object> list3 = Enumerable.Repeat(new object(), n).ToList(); sw.Restart(); ReinitializeAndCollect(list3); sw.Stop(); Console.WriteLine("ReinitializeAndCollect: {0} ms", sw.ElapsedTicks / 10000D); Console.WriteLine("==="); } } static List<object> Clear(List<object> list) { list.Clear(); return list; } static List<object> Reinitialize(List<object> list) { return new List<object>(); } static List<object> ReinitializeAndCollect(List<object> list) { list = new List<object>(); GC.Collect(); GC.WaitForPendingFinalizers(); return list; } } } 

我的结论基于我的普通核心i3处理器的结果:

在数千个元素的情况下 – 最好清除列表。 这是快速和内存效率。

如果收集有超过10万个元素 – 重新初始化变得更有吸引力。 如果在分析后认为此处存在瓶颈,请使用它。 重新初始化会非常快,但是如第三种方法testing所示,将来的垃圾收集将会像清除列表一样慢。

所以简短的回答是:如果你没有分析你的应用程序,使用Clear 。 重用对象是很好的。 如果你做了 – 你已经知道该怎么做了。

这将取决于很多因素,从长远来看,在您的计划中可能无所谓(足够数量)。

从msdn 文档 .Clear()是一个O(n)操作。

初始化一个新的实例将会有自己的开销(如果你保持这个集合的长度相同,则执行一个O(n)操作:即Add()调用)。

真的,testing这个的唯一方法是在你的程序中设置一些秒表,如果你真的认为它是值得的,看看效果如何。 在所有的可能性; 这不值得。

我的想法是,如果你已经创build了一个集合Clear() ,那么这就是为什么有一个Clear()方法的原因。

虽然这可能令人沮丧,但答案的确是这不重要。 两者之间的时差会非常小,所以对您的应用程序可能没有任何影响。 做什么导致更干净,更易于理解的代码,并尽量不编程微优化。

Clear()将删除所有元素,并维护现有的容量,而创build一个新的List将至less需要一个托pipe堆的分配(如果初始容量较小,可能会更多地添加项目)。

  • 如果您有大量项目,并且每次迭代中项目的数量大致相同,则使用“ Clear可能会稍微快一点。

  • 如果一次迭代中的项目数量非常大,那么在后续迭代中数量要小得多,然后使用Clear可能成本更高,因为您将在内存中保留一个不必要的大容量的列表。

当然,在很多情况下(大多数情况下),这个差别是微不足道的。

也许我在这里做了一些根本性的错误,但是在C#中开发一个ASP.NET应用程序时,使用Clear()和new时遇到了很大的不同。 我正在创build一个包含数据系列的统计图表。 对于每个图表,我有一个部分,我这样做:

 chart = new ChartistChart() { Title = "My fancy chart" }; series = new List<ChartistMetaValue>(); *some code for getting the statistics* chart.Series.Add(series); chartistLineCharts.Add(chart); 

那么另一个图表如下。

 chart = new ChartistChart() { Title = "My second fancy chart" }; series = new List<ChartistMetaValue>(); *some code for getting the statistics* chart.Series.Add(series); chartistLineCharts.Add(chart); 

这个工作正常, series被重新分配new ,但当我这样做

 series.Clear(); 

相反,我实际上清除chart.Serieschart.Series内的条目,以便统计页面最终只检索最后一个图表的系列。 我假设这里有一些链接,比如内存指针,这是一个与最初讨论的不同的问题,但这至less是一个重新selectClear() 。 也许有一种方法可以避免它。

我为自己做了几个testing。 结果(速度)是:

  • 对于小列表(例如3个项目),创build新列表的速度更快,但差异不大
  • 对于平均10个或更多的项目,最好清除列表。 对于价值types要好得多(例如3-4倍),价值时间要好20%。

但最终还是应用程序的configuration和整个应用程序的瓶颈。

如果你的对象是值types,我会使用Clear()来减less内存将来的分配。 否则,两种方法几乎完全相同。