Tzot

We must accept finite disappointment, but we must never lose infinite hope. -- Mattin Luther King
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

List<T> 和 Collection<T> 性能比较

Posted on 2008-08-19 17:51  Tzot  阅读(4194)  评论(2编辑  收藏  举报

List<T> 继承了接口:IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable

Collection<T>继承了接口:IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable

通过接口比较发现两者继承了相同的接口。以下是MSDN对两者的描述。

 

---------------------------------------MSDN 对List<T>的描述------------------------------------------------------------------------------------

List<(Of <(T>)>) 类是 ArrayList 类的泛型等效类。该类使用大小可按需动态增加的数组实现 IList<(Of <(T>)>) 泛型接口。

List<(Of <(T>)>) 类既使用相等比较器又使用排序比较器。

  • 诸如 Contains、IndexOf、LastIndexOf 和 Remove 这样的方法对列表元素使用相等比较器。类型 T 的默认相等比较器按如下方式确定。如果类型 T 实现 IEquatable<(Of <(T>)>) 泛型接口,则相等比较器为该接口的 Equals(T) 方法;否则,默认相等比较器为 Object..::.Equals(Object)。

  • 诸如 BinarySearch 和 Sort 这样的方法对列表元素使用排序比较器。类型 T 的默认比较器按如下方式确定。 如果类型 T 实现 IComparable<(Of <(T>)>) 泛型接口,则默认比较器为该接口的 CompareTo(T) 方法;否则,如果类型 T 实现非泛型 IComparable 接口,则默认比较器为该接口的 CompareTo(Object) 方法。如果类型 T 没有实现其中任一个接口,则不存在默认比较器,并且必须显式提供比较器或比较委托。

List<(Of <(T>)>) 不保证是排序的。 在执行要求 List<(Of <(T>)>) 已排序的操作(例如 BinarySearch)之前,您必须对 List<(Of <(T>)>) 进行排序。可使用一个整数索引访问此集合中的元素。此集合中的索引从零开始。List<(Of <(T>)>) 接受 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing) 作为引用类型的有效值并且允许有重复的元素。

性能注意事项

在决定使用 List<(Of <(T>)>) 还是使用 ArrayList 类(两者具有类似的功能)时,记住 List<(Of <(T>)>) 类在大多数情况下执行得更好并且是类型安全的。如果对 List<(Of <(T>)>) 类的类型 T 使用引用类型,则两个类的行为是完全相同的。但是,如果对类型 T 使用值类型,则需要考虑实现和装箱问题。

如果对类型 T 使用值类型,则编译器将特别针对该值类型生成 List<(Of <(T>)>) 类的实现。这意味着不必对 List<(Of <(T>)>) 对象的列表元素进行装箱就可以使用该元素,并且在创建大约 500 个列表元素之后,不对列表元素装箱所节省的内存将大于生成该类实现所使用的内存。

确保用于类型 T 的值类型实现 IEquatable<(Of <(T>)>) 泛型接口。如果未实现,则诸如 Contains 这样的方法必须调用 Object..::.Equals(Object) 方法,后者对受影响的列表元素进行装箱。如果值类型实现 IComparable 接口,并且您拥有源代码,则还应实现 IComparable<(Of <(T>)>) 泛型接口以防止 BinarySearch 和 Sort 方法对列表元素进行装箱。如果您不拥有源代码,则将一个 IComparer<(Of <(T>)>) 对象传递给 BinarySearch 和 Sort 方法。

使用 List<(Of <(T>)>) 类的特定于类型的实现,而不是使用 ArrayList 类或自己编写强类型包装集合,这样是很有好处的。原因是您的实现必须做 .NET Framework 已经为您完成的工作,并且公共语言运行库能够共享 Microsoft 中间语言代码和元素据,这是您的实现所无法做到的。

 

-----------------------------------------------------MSDN 对Collection<T>的描述----------------------------------------------------------------------------------

通过创建 Collection<(Of <(T>)>) 类的一个构造类型的实例,可以立即使用该类;您只需指定要包含在集合中的对象类型即可。此外,您可以从任意构造类型派生自己的集合类型,或者从 Collection<(Of <(T>)>) 类本身派生出泛型集合类型。

Collection<(Of <(T>)>) 类提供了受保护的方法,这些方法可用于在添加和移除项、清除集合或设置现有项的值时自定义该类的行为。

大多数 Collection<(Of <(T>)>) 对象都可以被修改。但是,不能修改使用只读 IList<(Of <(T>)>) 对象初始化的 Collection<(Of <(T>)>) 对象。有关此类的只读版本,请参见 ReadOnlyCollection<(Of <(T>)>)。可使用一个整数索引访问此集合中的元素。 此集合中的索引从零开始。Collection<(Of <(T>)>) 接受 nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing) 作为引用类型的有效值并且允许有重复的元素。

给实现者的说明:

提供此基类旨在使实施者更易于创建自定义集合。实现者最好扩展此基类,而不是创建自己的类。

 

 

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Stopwatch sw = new Stopwatch();
 6             sw.Start();
 7             ArrayList arrayListObjects = new ArrayList();
 8 
 9             for (int i = 0; i < 100000; i++)
10             {
11                 arrayListObjects.Add(new Member { PropertyOne = new Random().Next(100010000), PropertyTwo = new Random().Next(100010000) });
12             }
13             sw.Stop();
14             Console.WriteLine("ArrayList Performance: "+sw.ElapsedMilliseconds.ToString());
15 
16             sw.Reset();
17             sw.Start();
18             List<object> listObjects = new List<object>();
19             for (int i = 0; i < 100000; i++)
20             {
21                 listObjects.Add(new Member { PropertyOne = new Random().Next(100010000),PropertyTwo = new Random().Next(100010000)});
22             }
23             sw.Stop();
24             Console.WriteLine("List<T> Performance: "+sw.ElapsedMilliseconds.ToString());
25 
26             sw.Reset();
27             sw.Start();
28 
29             Collection<object> collectionObjects = new Collection<object>();
30 
31             for (int i = 0; i < 100000; i++)
32             {
33                 collectionObjects.Add(new Member { PropertyOne = new Random().Next(100010000), PropertyTwo = new Random().Next(100010000) });
34             }
35 
36             sw.Stop();
37 
38             Console.WriteLine("Collection<T> Performance: "+sw.ElapsedMilliseconds.ToString());
39 
40             Console.Read();
41         }
42     }
43 
44     public class Member
45     {
46         public int PropertyOne { getset; }
47         public int PropertyTwo { getset; }
48     }

 

 

 

通过测试添加100000个对象发现,三者的性能是非常的接近的!