集合
List<T>是与数组相当的集合类,还有其他类型的集合:队列,栈,链表,和字典
一、集合接口和类型
大多数集合类都可在System.Collections和 System.Collections.Generic名称空间中找到。泛型集
合类位于System.Collections.Generic名称空间中:专用于特定类型的集合类位于System.Collections.Specialized名称空间中。 线程安全的集合类位于System.Collections.Concurrent名 称空间中。当然,组合集合类还有其他方式。 集合可以 根据集合类实现的接 口 组合为列表、集合和字典。
二、列表
.net framework为动态列表提供了泛型类List<T>,这个类实现了IList,ICollection,IEnumerable,IList<T>,ICollection<T>,和IEnumerable<T>。
1.创建列表:构造函数
(1)集合初始值设定项
(2)添加元素Add()
(3)插入Insert()
(4)访问:索引器方式,foreach遍历,除了使用forcach语句之外,List<T>供了ForEach()方 法,该方法用Action<T> 参数声明。
(5)删除元素RemoveAt(),Remove(obj)
(6)搜索:IndexOf(),LastIndexOf(),FindIndex(),Find(),FindLast(),检查元素是否存在Exists()。
(7)排序:Sort(),此方法有几个重载,除了这个,其余的都是有参数的。只有集合中的元素实现了IComparable接口,才能使用不带参数的Sort()方法。排序的另一种方式是使用重载的 sort()方 法,该 方法需要一个 Comparison<T>委托,该方法有两个T类型的参数,返回类型为int,0,-1,1.
(8)类型转换:使用List<T>方法的ConvertAll<TOutput>()方法,可以把所有类型的集合转换为另一种类型。ConvertAll<T Output>()方 法使用个 Convert委托,泛型类型 TInput和 TOutput用 于转换。 Thput是 委托方法的 参数,TOutput是 返回 类型。
(9)只读集合AsReadOnly()返回ReadOnlyCollection<T>类型的对象
三、队列
队列是其元素以先进先出FIFO的方式来处理的集合。先放入队列中的元素会先读取。队列使用 System.Collections.Generic名 称空间中的泛型类 Queue<T>实现。在 内部, Queue<T>类使用 T类型的数组,这类似于List<T>类型。 它实现ICollection和 IEnummble<T> ,但没有实现ICollection<T>接口,因 为这个接 口 定义的Add()和 Rmove()方 法不能 用于队列。Queue<T>因为没有实现IList<T>接口,所以不能用索引器访问队列。队列只允许在队列中添加元素,该元素会放在队列的尾部(使用Enqueue()方法),从队列的头部获取元素(使用Dequeue()方法)
非泛型类 Qucue的 默认构造函数与此不同,它会创建一个包含 彡 项的空数组。使用构造函数的重载版本 ,还可以 将实现 了 IEnunerable() 接 口的其他集合复制到队列中。
四、栈
栈是与队列类似的另一个窗口,只是要使用不同的方法访问栈。最后添加到栈中的元素会最先读取,是一个后进先出LIFO的窗口。用Push()yyifd栈中添加元素,用Pop()方法获取最近添加的元素。Statck<T>类实现IEnumerable<T>和ICollection接口
五、链表
LinkedList<T>是一个双向链表,其元素指向它前面和后面的元素。链表的 优点是,如 果将元素插入列表的中间 位置,使用链表就会非常快。 在插入一个元素时,只需修改上一个元素的 Next引 用和下一个元素的 Previous引用,使 它们引用所插入的元素。 在List<T>中 ,插 入一个元素时,需要移动该元素后面的 所有元素。当 然,链表也有缺点。 链表的 元素只能一个接一个地访问,这需要较长的时间来查找位于链表中间或尾部的元素。链表不仅能 在列表中 存储元素。 存储元素时,链表还必须存储每个元素存储下一个元素和上一个 元 素 的信 息 。LinkedList<T> 包 含 LinkedListNode<T>类 型 的元 素。LinkedList<T>定 义的 成员可以 访问 链表中的 第一个和最后一个元素(First,Last)、 在指定位置插入元素(AddAfter()、 AddBefore()、 AddFirst()和 AddLast()方 法),删 除指定位置的 元素Remove()、RemoveFirst()和 RemoveIast()方 法)、 从链表的开头(Find())或 结 尾(FindLast())开 始搜索元素。
六、有序列表
如果需要基于键对所需集合排序,就 可以 使 用SortedList<Tkey,TValue>类。这个类按照键给元素排序。这个体例中的值和键都可以使用任意类型。可以使用foreach语句遍历该列表。枚举器 返回的元素是KeyValuePair<TKey,TValue>型 ,其中包含键和值。键可以用Key属性访问 ,值可以用Value属性访问 。也可以使用Values和Keys属性访问值和键。因为 Values,属性返回IList<TValue>,Keys属 性返回IList<TKey>,所以可通过 foreach语 旬使用这些属性。如果 尝试使 用索引 器访问 一个元素,但所传递的键不存在,就 会抛出 一个 KeyNotFoundException的异常。 为了 避免这个异常,可以使用ContainsKey()方法,如果所传递的键存在于集合中,这个方法就返回 true,也可以调用TryGetValue方法,该方法尝试获得指定键的值。 如果指定键对应的值不存在,该方法就不会抛出 异常。
七、字典
字典表示一种非常复杂的数据结构,允许按照某个键来访问元素。字典也称为映射或散列表。主要特性是能根据键快速查找值。也可以自由添加和删除元素。这有点像List<T>类,但没有在内存中移动后续元素的开销。
1.键的类型:用途字典中键的类型必须重写Object类的GetHashCode()方法。只是字典类需要确定元素的位置 ,它就要调用GetHashCode()方法。int方法返回的血由字典用于计算在对应位置放置元素的索引。 这里不介绍这个算法。我们只需知道,它涉及素数,所 以 字典的容量是一个素数。GetHashCode()方 法的实现代码必须满足如下要求:
● 相同的对象应总是返回相同的值。
● 不同的对象可以返回相同的值。
● 它应执行得比 较快,计算的开销不大。
● 它不能抛 出异常。
● 它应至少使用一个实例字段。
● 散列代码值应平均分布在 血 可以存储的整个数字范围上。
· 散列代码最好在对象的生存期中不发生变化。
字典的性能取决于GetHashCode()方法的实现代码。
声明方式:Dictionary<TKey,TValue>
2.示例
3.Lookup类
3.有序字典
八、集
包含中重复元素的集合称为集Set,.net包含两个集HashSet<T>和SortedSet<T>。ISet<T>接口 提供的 方 法可以 创建合集、 交 集,或者给出一个集是另 一个集的 超 集或子集的 信 息。
九、可观察的集合
如果需要集合中的 元素何时删除或添加的 信息,就可以 使用 ObservableCollection<T> 类。 这个类是为 WPF定 义的,这样UI就可以得知集合的变化,因此这个类在程序集 WmdowsBase中 定义,同时 用户需要引用这个程序集。 这个类的 名称空间是System.Collections.ObjectModel。
ObservableCollection<T>派生自Collection<T>基类 ,该基类可用于创建 自 定义集合,并 在内 部
使用List<T>类。 重 写基类中 的 虚方法SetItem()和RemoveItem(),以 触发CollectionChanged事件。 这个类的 用户可以 使用INotifyCollectionChanged接 口 注册这个事件。
十、位数组
十一、并发集合、
.net包 含的 新名称空间System.Collections.Concurrent有几个线程安全的集合类。 线程安全的集合可防止多个线程以 相互冲突的 方式访问 集合。为了对集合进行线程安全的访问,定义了IProducerConsumerCollection<T>接口。这个接口中最重要的方法是TryAdd()和TryTake()
十二、性能
MSDN文档中集合的方法常常有性能提示,给出了以大O记号表示的操作时间
O(1),O(log n),O(n)