数组和Array类实现的接口 数组大小是固定的。如果元素个数是动态的就应该使用集合类。
集合类型:List<T> 、队列、栈、链表、字典和集。
多线程中使用的位数组和并发集合。
集合类区别和性能差异:
泛型集合类 在System.Collections.Generic 名称空间中。
特定类型的集合类 位于System.Collections.Specialized名称空间汇总。
线程安全的集合类位于System.Collections.Concurrrent名称空间中。
不可变的集合类在System.Collections.Immutable 命名空间。
集合可以根据集合类实现的接口组合为列表、集合和字典。
List<T>泛型-- 如果列表容量改变了,整个集合就要重新分配到一个新的内存块中。
Array.Copy()方法将数组中的元素复制到新数组中。为节省时间,如果事先知道列表中的元素个数,就可以用构造函数定义其容量。
//声明一个int泛型集合并初始化一个容量为10的元素集合 List<int> intList=new List<int>(10); //使用Capacity 属性可以获取和设置集合的容量 intList.Capacity=20;
容量于集合中元素的个数不同。集合中的元素个数可以用Count属性读取 。
容量 总是大于或等于元素个数。只要不把元素添加到列表中,元素个数就是0。
如果已经将元素添加到列表中,且不希望添加更多的元素,就可以调用TrimExcess()方法 ,去除不需要的容量。但是,因为重新定位需要时间,所以如果元素个数超过了容量的90%,TrimExcess()方法就什么也不会做。intList.TrimExcess();
1:集合初始值设定项。
var intList=new List<int>(){1,2};
2:添加元素 intList.Add(3);
使用AddRange()方法 可以一次给集合添加多个元素,因为AddRange()方法的参数是IEnumerable<T>类型的对象,所以也可以传递一个数组。
如果知道集合元素个数 将可以将实现了IEnumerable<T>类型的任意对象传递给类的构造函数。
1 var racers=new List<Racer>{ 2 new Racer[]{ 3 new Racer(12,"Jochen","Rindt","Austria",6), 4 .... 5 ... 6 } 7 }
3:插入元素
intList.Insert();
方法 InsertRange()体东了插入大量元素的功能,类似于前面的AddRange()方法。
如果索引集大于集合中的元素个数,就抛出ArgumentOutRangeException类型。
4:访问元素
实现了IList和IList<T>接口的所有类都提供了一个索引器。所以可以使用索引器,通过
传递元素好来访问元素。
List<T>集合类实现了IEnumerable接口,所以可以使用foreach遍历元素个数
for循环遍历,并使用索引器访问每一项。
可以通过索引访问的集合类有ArrayList、StringCollection和List<T>。
5:删除元素
可以利用索引,删除元素。也可以传递要删除的元素 RemoveAt();
如删除第4个元素 racers.RemoveAt(3);
也可以直接将Racer对象传送给Remove()方法,来删除这个元素。
按索引删除比价快,因为必须在集合中搜索要删除的元素。Remove()放在现在集合中搜索,用IndexOf()方法获取元素的索引,在使用该索引删除元素。IndexOf()方法先检查元素类型是否实现
IEquatable<T>接口。如果是,就调用这个接口的Equals()方法,确定集合中的元素是否等于传递给Equals()方法的元素。如果没有实现这个接口,就使用Object类的Equals()方法比较这些元素。
Object类中的Equals()方法默认实现代码对值类型进行按位比较,对引用类型只比较其引用。
RemoveRange()方法可以从集合中删除许多元素。它的第一个参数指定了开始删除的元素指引,第二个参数指定了要删除的元素个数。RemoveRange(index,count);
要从集合中删除有指定特征的所有元素,可以使用RmoveAll()方法,这个方法在搜索元素时使用Predicate<T>参数。要删除集合中的所有元素,可以使用ICollection<T>接口定义的Clear()方法。
6:搜索
要获得要查找的元素的索引,或者搜索元素本身,可以使用方法有IndexOf()、LastIndexOf() FindIndex() FindLastIndex() Find() FindLast().所以只检查元素是否存在,List<T>类就体东了Exists()方法。
IndexOf()方法需要将一个对象作为参数,如果在集合中找到该元素,这个方法就返回元素的索引,如果没有找到该元素,就返回-1.IndexOf()方法使用IEquatable<T>接口来比较元素。
使用IndexOf()方法,还可以指定不需要搜索整个集合,但必须指定从哪个索引开始搜索以及比较要迭代的元素个数。
FindIndex() 方法可以用来搜索某个特征的元素,FindexIndex()方法需要一个
Predicate类型的参数。
public int FindIndex(Predicate<T> match);
Predicate<T>类型时一个委托。该委托返回一个布尔值。并且需要把类型T作为参数。如果
Predicate<T>委托返回true,就表示有一个匹配元素,并且找到相应的元素。如果没有返回false,就表示没有找到元素,搜索将继续。
public delegate bool Predicate<T>(T obj);
FindIndex除了可以用类型T 作为方法参数外。可以用lambda表达式。效果是一样的
racers.FindIndex(r=>r.Country=="Finland");
racers.FindIndex(new FindCountry("Finland").FindeCountryPredicate);
FindLastIndex()方法:从集合汇总的最后一个元素开始向前搜索某个索引。
FindIndex()方法 返回所查找元素的索引。除了活的索引之外。还可以直接获得集合中的元素。
FindLast()方法,查找与Predicate<T>类型匹配的最后一项。
FindAll()方法。FindAll()方法使用的Predicate<T>类型匹配的所有项。FindeAll方法找到第一项后,不会停止搜索,而是继续迭代集合中的每一项。并返回Predicate<T>类型是true的所有项。
7.排序
List<T>类可以使用Sort()方案对元素排序。Sort()方法使用快速排序算法。比较所有元素,直接整个列表排好序为止。
只有集合中的元素实现了IComparable<T>接口,才能使用不带参数的Sort()方法。
Sort()重载方法。
如果需要按照元素类型不默认支持的方法排序,就应使用其他技术。
如传递一个实现了IComparer<T>接口对象。
Comparsion<T>是一个方法委托,该方法有两个T型参数,返回类型为int型
public delegate int Comparsion<T>(T x,T y)
lambda racers.Sort((r1,r2)=>r2.Wins.CompareTo(r1.Wins));
调用Reverse()方法,逆转整个集合的顺序
只读集合
创建集合后他们就是可读写的。否则就不能给他们填充值了。但是,填充完集合后,
可以创建只读集合。
List<T>集合的AsReadOnly()方法返回ReadOnlyCollection<T>类型的对象。
ReadOnlyCollection<T>类实现的接口与List<T>集合相同。但所有修改集合的方法和属性都抛出NoSupportedException异常。除了List<T>的接口之外,ReadOnlyCollection<T>还实现了IReadOnlyCollection<T>和IReadOnlyList<T>接口。因为这些接口的成员,集合不能修改。
11.4队列
队列先进先出(FirstIn,FirstOut FIFO)的方式来处理集合。
队列的例子 有打印队列中等待处理打打印任务,以及按循环方式等待CPU处理的线程。
元素还有优先级。
可以为一组队列建立一个数组,数组中的一项代表一个优先级。在每个数组项中都有一个队列。其中按照FIFO的方式进行处理了。
队列使用System.Collections.Generic名称空间中的泛型类Queue<T>实现。
在内部Queue<T>类使用T类型的数组,它实现了ICollection和IEnumerable<T>接口。
但没有实现ICollection<T>接口 因为这个接口定义的Add()和Remove()方法不能用于队列。
因为Queue<T>类没有实现IList<T>接口,所以不能用索引器访问队列。队列只允许在队列中添加元素。该元素会放在队列的尾部(使用Enqueue()方法)从队列的头部获取元素(使用Dequeue()方案)。
Dequeue()会读取和删除元素。如果调用Dequeue()方法时,队列中不再有元素。就抛出一个InvalidOperationException类型的异常。
Peek()方法从队列的头部读取一个元素,但不删除它。
TrimExcess TrimExcess()方法重新设置队列的容量,Dequeue()方法从队列中删除元素,但它不会重新设置队列的容量,要重队列的头部去除空元素,应使用TrimExcess()方法。
泛型Queue没有定义容量,容量就会递增,从而包含4、 8、 16、 32个元素类似于List<T>类 队列的熔炼炉也是总根据需要成倍增加。
非泛型类Queue的默认构造函数于此不同 它会穿件一个包含32项的空的初始数组。
使用构造函数的重载版本,还可以将实现了IEnumerable<T>接口的其他集合复制到队列中。