【发布时间】:2011-03-13 19:19:31
【问题描述】:
List<T>.Remove(T) 是否比 .NET 集合中的 List<T>.RemoveAt(int) 方法快?值类型或引用类型的速度是否不同?
【问题讨论】:
标签: .net generics collections
List<T>.Remove(T) 是否比 .NET 集合中的 List<T>.RemoveAt(int) 方法快?值类型或引用类型的速度是否不同?
【问题讨论】:
标签: .net generics collections
使用System.Diagnostics.Stopwatch()
我会创建一个小控制台应用程序来检查哪个更快。
【讨论】:
鉴于 .Net 感染的是向量(或数组),而不是链表,RemoveAt() 更快。
【讨论】:
简单回答:
一般来说,RemoveAt 更快,但并不总是非常快。
长答案:
让我们先考虑找到合适的项目。 Remove 方法必须在列表中搜索与给定对象匹配的项目,因此通常是 O(n) 时间。列表上的RemoveAt 可以简单地索引给定的项目,因此是O(1)。
现在,从列表末尾删除一个项目当然总是O(1),但通常删除一个项目需要O(n) 时间,因为需要进行重新洗牌(将删除后的项目向前移动)。因此,在一般情况下,对于 Remove 和 RemoveAt,移除的总时间复杂度分别为 O(n) + O(n) 或 O(n) + O(1),因此在任何一种情况下都只是 O(n)。但是,RemoveAt 保证至少一样快,尽管缩放是相同的,除非您知道您将在结尾处/接近结尾处移除它。
【讨论】:
Remove(T) 在内部调用 RemoveAt(int) 因此,直接执行 removeAt 会更快。
但是你想达到什么目的?
【讨论】:
List.Remove(T) 在其实现中使用 IndexOf 和 RemoveAt(int)。所以 List.RemoveAt(int) 更快。
public bool Remove(T item)
{
int index = this.IndexOf(item);
if (index >= 0)
{
this.RemoveAt(index);
return true;
}
return false;
}
【讨论】:
this.IndexOf(item) 代码在性能方面付出了巨大的代价,因为它会扫描整个后备数组,直到找到要删除的项目。特别是当要删除的项目位于列表末尾时,它会在每次请求删除时扫描整个列表。当我试图借助 List<int> 类来实现堆栈数据结构时,它发生在我身上。随着列表大小的显着增长,例如超过 10K 元素,使用 Remove(T) 从末尾删除可能会破坏您的程序。