C#学习总结之集合
一、集合接口和类型
命名空间:
集合类型 | 命名空间 |
一般集合 | System.Collections |
泛型集合 | System.Collections.Generic |
特定类型集合 | System.Collections.Specialized |
线程安全集合 | System.Collections.Concurrent |
不可变集合 | System.Collections.Immutable |
接口说明:
接口 | 说明 |
IEnumerable<T> | 如果将foreach语句用于集合,就需要IEnumerable接口。此接口定义了GetEnumerator()方法,返回一个实现了IEnumerator接口的枚举。 |
ICollection<T> | ICollection<T>接口由泛型集合类实现。使用这个接口可以获得集合中的元素个数(Count属性),把集合复制到数组中(CopyTo()方法),从集合添加和删除元素(Add(),Remove(),Clear())。 |
IList<T> |
IList<T>接口用于可通过位置访问其中的元素列表,此接口定义了一个索引器,可以在集合的指定位置插入或删除某些项(Insert()和RemoveAt()方法)。IList<T>接口派生自ICollection<T>接口。 |
ISet<T> |
ISet<T>接口由集实现。集允许合并不同的集,获得两个集的交集,检查两个集是否重叠。ISet<T>接口派生自ICollection<T>接口。 |
IDictionary<TKey,TValue> | IDictionary<TKey,TValue>接口由包含键和值的泛型集合类实现。使用此接口可以访问所有的键和值,使用键类型的索引器可以访问某些项,还可以添加或删除某些项。 |
ILookup<TKey,TValue> | 类似于IDictionary<TKey,TValue>接口,可以通过一个键包含多个值。 |
IComparer<T> | 由比较器实现,通过Compare()方法给集合中的元素排序。 |
IEqualityComparer<T> | 由比较器实现,用于字典中的键。使用此接口可对对象进行相等性比较。 |
IProductConsumerCollection<T> | .NET4.0后添加,支持新的线程安全的集合类。 |
IReadOnlyCollectiton<T> IReadOnlyList<T> IReadOnlyDictionary<TKey,TValue> |
用于初始化后不能修改的集合,这些接口的成员只允许检索对象,不能添加或修改它们。 |
IImmutableArray<T> IImmutableList<T> IImmutableQueue<T> IImmutableSet<T> IImmutableDictionary<TKey,TValue> |
不可变接口定义了用于不可变集合的方法和属性,这些集合在初始化后不能修改。 |
二、列表
调用默认构造函数创建列表对象:
var intList = new List<int>();
*使用默认构造函数创建空列表,元素添加到列表中后,列表容量会首先扩大到可容纳4个元素,每次超过容量后会重新设置为原来的2倍。列表容量改变,就要重新分配到一个新的内存块中,创建一个新的数组,使用Array.Copy()方法将旧的数组中的元素复制到新的数组中。
获取和设置集合的容量:
intList.Capacity = ;
获取集合元素的数量(Count属性):
Console.WriteLine(intList.Count);
释放不需要的容量:
intList.TrimExcess();
- 集合初始化设定项
,};
*集合初始值设定项没有反映在已编译的程序集的IL代码中,编译器会把集合初始值设定项变成对初始值设定项列表中的每一项调用Add()方法。
- 添加元素
intList.Add();
intList.AddRange(new int[]{1,2,3});
- 插入元素
intList.Insert(,); intList.InsertRange(,,,,});
- 访问元素
使用for循环遍历集合中的元素,通过索引器访问元素:
; i < intList.Count; i++) { Console.WriteLine(intList[i]); }
使用foreach语句遍历集合中的元素:
foreach (int i in intList) { Console.WriteLine(i); }
使用ForEach()方法:
intList.ForEach(Console.WriteLine);
- 删除元素
使用RemoveAt()方法删除元素:
intList.RemoveAt();
使用Remove()方法删除元素:
]; intList.Remove(i);
*按索引删除比较快,因为必须在集合中搜索要删除的元素。Remove()方法先检查元素类型是否实现了IEquatable<T>接口。如果是,就调用这个接口的Equals()方法,确定集合中的元素是否存在等于传递给Equals()方法的元素。如果没有实现这个接口,就使用Object类的Equals()方法比较这些元素。Object类中的Equals()方法的默认实现代码对值类型进行按位比较,对引用类型只比较其引用。
使用RemoveRange()方法删除元素(索引加位数):
intList.RemoveRange(,);
使用RemoveAll()方法删除指定特性的所有元素:
== );
使用Clear()方法删除集合中的所有元素:
intList.Clear();
- 搜索
使用Exists()方法检查元素是否存在:
intList.Exists(it => it == );
使用IndexOf()方法返回指定元素在集合中的索引,如果没有找到,则返回-1:
Console.WriteLine(intList.IndexOf());
使用FindIndex()、FindLastIndex()方法返回指定元素在集合中的索引:
);
int lastIndex = intList.FindLastIndex(r => r == 6);
使用Find()方法返回集合中指定的元素:
);
使用FindAll()方法获取与Predicate<T>类型匹配的所有项:
List<); foreach (int i in newIntList) { Console.WriteLine(i); }
- 排序
使用Sort()方法排序:
intList.Sort();
- 类型转换
使用ConvertAll<TOutput>()方法把集合转换为另一种类型:
List<string> stringList = intList.ConvertAll<string>(r => r.ToString() + "(I'm string)");
使用AsReadOnly()方法返回只读集合:
ReadOnlyCollection<int> readOnlyCollection = intList.AsReadOnly();
三、队列
队列是其元素以先进先出的原则来处理的集合,队列使用System.Collections.Generic命名空间下的泛型类Queue<T>实现。它实现了ICollection和IEnumberable<T>接口,但没有实现ICollection<T>接口,因此不能使用Add()和Remove()方法,且没有实现IList<T>接口,所以不能使用索引器访问队列。
Queue<T>类的方法说明
Queue<T>类的成员 | 说明 |
Count | Count属性返回队列中的元素个数 |
Enqueue | Enqueue()方法在队列一端添加一个元素 |
Dequeue | Dequeue()方法在队列的头部读取和删除一个元素。如果调用时队列中没有元素,则抛出一个InvalidOperationException类型的异常 |
Peek | Peek()方法从队列的头部读取一个元素,但不删除它 |
TrimExcess | TrimExcess()方法重新设置队列的容量。Dequeue()方法从队列中删除元素,但它不会重新设置队列的容量。要从队列的头部去除空元素,应使用TrimExcess()方法 |
public class Document { public string Title { get; private set; } public string Content { get; private set; }
public Document(string title, string content) { this.Title = title; this.Content = content; } } public class DocumentManager { private readonly Queue<Document> documentQueue = new Queue<Document>(); public void AddDocument(Document doc) { lock (this) { documentQueue.Enqueue(doc); } } public Document GetDocument() { Document doc = null; lock (this) { doc = documentQueue.Dequeue(); } return doc; } public bool IsDocumentAvailable { get { ; } } }
四、栈
栈是一个后进先出的容器,使用Push()方法在栈中添加元素,用Pop()方法获取最近添加的元素。
Stack<T>类的方法说明
Stack<T>类的成员 | 说明 |
Count | 返回栈中的元素个数 |
Push | 在栈顶添加一个元素 |
Pop | 从栈顶删除一个元素,并返回该元素,如果栈是空的,就抛出InvalidOperationException异常 |
Peek | 返回栈顶的元素,但不会删除它 |
Contains | 确定某个元素是否在栈中,如果是,就返回true |
var alphabet = new Stack<char>(); alphabet.Push('A'); alphabet.Push('B'); alphabet.Push('C'); foreach (char item in alphabet) { Console.WriteLine(item); } Console.ReadLine(); //返回内容为C、B、A
五、链表
LinedList<T>是一个双向链表,其元素指向它前面和后面的元素。
链表的优点:在插入一个元素时,只需要修改上一个元素的Next引用和下一个元素的Previous引用即可。
链表的缺点:链表的元素只能一个接一个地访问,这需要较长的时间来查找位于链表中间或尾部的元素。
LinkedListNode<T>类型属性说明
属性 | 说明 |
List | 返回与节点相关的LinkedList<T>对象 |
Next | 用于遍历列表,返回当前节点之后的节点 |
Previous | 用于遍历列表,返回当前节点之前的节点 |
Value | 返回与节点相关的元素 |
六、有序列表
如果需要基于键对所需集合排序,可以使用SortedList<TKey,TValue>类。
var books = new SortedList<string, string>(); books.Add("Professional WPF Programming", "978-0-470-04180-2"); books.Add("Professional ASP.NET MVC 3", "978-1-1180-7658-3"); books["Beginning Visual C# 2010"] = "978-0-470-50226-6"; books["Professional C# 4 and .NET 4"] = "978-0-470-50225-9"; foreach (var book in books) { Console.WriteLine("{0} , {1}", book.Key, book.Value); } Console.ReadLine();
*如果使用索引器访问一个元素,若所传键值不存在,就会抛出一个KeyNotFoundException类型的异常。为了避免异常发生,可以使用ContainsKey()方法判断列表中是否有指定键值。也可以调用TryGetValue()方法尝试获得指定键的值。
string isbn; string title = "Professional C# 7.0"; if (!books.TryGetValue(title,out isbn)) { Console.WriteLine("{0} not found", title); }
七、字典
字典是一种可以按照某个键来访问元素的集合,用作字典中键的类型必须重写object类的GetHashCode()方法。字典的容量是一个素数,如果指定的容量不是素数的值,Dictionary<TKey,TValue>类会使用传递给构造函数的整数后面紧接着的一个素数来指定容量。
- Dictionary<TKey,TValue>类
使用Add()方法添加元素:
var myDictionary = new Dictionary<string, string>(); myDictionary.Add(", "Jack");
使用索引器添加元素:
myDictionary["] = "Mike";
使用TryGetValue()方法检查键值是否存在,若存在则返回true,否则返回false:
string person; myDictionary.TryGetValue(", out person);
- Lookup<TKey,TValue>类:
类似Dictionary<TKey,Tvalue>类,但把键映射在一个值集上。Lookup<TKey,Tvalue>类不能像一般字典那样创建,必须调用ToLookup()方法。
class Program { static void Main(string[] args) { var racers = new List<Racer>(); racers.Add(,)); racers.Add(,)); racers.Add(,)); racers.Add(,)); racers.Add(,)); var lookupRacers = racers.ToLookup(r => r.Country); foreach (Racer r in lookupRacers["Australia"]) { Console.WriteLine(r); } Console.ReadLine(); } } public class Racer { public int Id { get; private set; } public string FirstName { get; set; } public string LastName { get; set; } public string Country { get; set; } public int Wins { get; set; } public Racer(int id, string firstName, string lastName, string country, int wins) { this.Id = id; this.FirstName = firstName; this.LastName = lastName; this.Country = country; this.Wins = wins; } ) { } public override string ToString() { return String.Format("{0} {1}", FirstName, LastName); } }
- SortedDictionary<TKey,TValue>类
SortedDictionary<TKey,TValue>类是一个二叉搜索树,其中的元素根据键来排序。该键的类型必须要实现Icomparable<TKey>接口。
八、集
包含不重复元素的集合称为"集(set)",.NET Framework包含两个集(HashSet<T>和SortedSet<T>)。HashSet<T>集包含不重复元素的无序列表,SortedSet<T>集包含不重复元素的有序列表。
方法 | 说明 |
Add | 返回一个布尔值,说明是否添加了元素 |
IsSubSetOf | 是否为子集 |
IsSupersetOf | 是否为超集 |
Overlaps | 确定是否当前的 Hashset对象和指定的集合共享通用元素 |
UnionWith | 并集 |
ExceptWith | 删除指定集合中的元素 |
var companyTeams = new HashSet<string>() { "Ferrari", "McLaren", "Mercedes" }; var traditionalTeams = new HashSet<string>() { "Ferrari", "McLaren" }; var privateTeams = new HashSet<string>() { "Red Bull", "Toro Rosso", "Force India", "Sauber" }; if (privateTeams.Add("Williams")) { Console.WriteLine("Williams Added"); } if (!companyTeams.Add("McLaren")) { Console.WriteLine("McLaren was already in this set"); } if (traditionalTeams.IsSubsetOf(companyTeams)) { Console.WriteLine("TraditionalTeams is subset of companyTeams"); } if (companyTeams.IsSupersetOf(traditionalTeams)) { Console.WriteLine("CompanyTeams is a superset of traditionalTeams"); } traditionalTeams.Add("Williams"); if (privateTeams.Overlaps(traditionalTeams)) { Console.WriteLine("At least one team is the same with the traditional and private teams"); } var allTeams = new SortedSet<string>(companyTeams); allTeams.UnionWith(privateTeams); allTeams.UnionWith(traditionalTeams); Console.WriteLine(); Console.WriteLine("All teams"); foreach (var team in allTeams) { Console.WriteLine(team); } allTeams.ExceptWith(privateTeams); Console.WriteLine(); Console.WriteLine("no private team left"); foreach (var team in allTeams) { Console.WriteLine(team); } Console.ReadLine();
九、可观察的集合
如果需要集合中的元素何时删除或添加的信息,就可以使用ObservableCollection<T>类,这个类的命名空间是System.Collections.ObjectModel。用户可以使用INotifyCollectionChanged接口注册CollectionChanged事件。
NotifyCollectionChangedEventArgs属性说明
属性 | 说明 |
Action | 是否添加或删除一项的信息 |
OldItems | 列出删除的项 |
NewItems | 列出新增的项 |
class Program { static void Main(string[] args) { var data = new ObservableCollection<string>(); data.CollectionChanged += Data_CollectionChanged; data.Add("One"); data.Add("Two"); data.Insert(, "Three"); data.Remove("One"); Console.ReadLine(); } static void Data_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { Console.WriteLine("action: {0}", e.Action.ToString()); if (e.OldItems != null) { Console.WriteLine("starting index for old item(s): {0}", e.OldStartingIndex); Console.WriteLine("old item(s) :"); foreach (var item in e.OldItems) { Console.WriteLine(item); } } if (e.NewItems != null) { Console.WriteLine("starting index for new item(s): {0}", e.NewStartingIndex); Console.WriteLine("new item(s): "); foreach (var item in e.NewItems) { Console.WriteLine(item); } } Console.WriteLine(); } }
十、位数组
如果需要处理的数字有许多位,可以使用BitArray类和BitVector32结构。BitArray类位于命名空间System.Collectioins中,BitVector32结构位于命名空间System.Collections.Specialized中。区别:BitArray可以重新设置大小,BitVector32结构仅包含32位。
BitArray类:
BitArray类的成员 | 说明 |
Count Length | Count和Length属性的get访问器返回数组中的位数。使用Length属性还可以定义新的数组大小,重新设置集合的大小。 |
Item Get Set |
可以使用索引器读写数组中的位。索引器是布尔类型,除了使用索引器之外,还可以使用Get()和Set()方法访问数组中的位。 |
SetAll |
根据传送给该方法的参数,SetAll()方法设置所有位的值。 |
Not | Not()方法对数组中所有位的值取反 |
And Or Xor |
使用And()、Or()、Xor()方法,可以合并两个BitArray对象。And()方法执行二元AND,Or()方法执行二元OR,Xor()方法是异或操作。 |
BitVector32结构:
BitVector32结构的成员 | 说明 |
Data | Data属性把BitVector32结构中的数据返回给整数 |
Item | BitVector32的值可以使用索引器设置。索引器是重载的——可以使用掩码或BitVector32.Section类型的片段来获取和设置值。 |
CreateMask | 这是一个静态方法,用于为访问BitVector32结构中的特定位创建掩码。 |
CreateSection | 这是一个静态方法,用于创建32位中的几个片段。 |
C#学习总结之集合的更多相关文章
- 软件测试之loadrunner学习笔记-02集合点
loadrunner学习笔记-02集合点 集合点函数可以帮助我们生成有效可控的并发操作.虽然在Controller中多用户负载的Vuser是一起开始运行脚本的,但是由于计算机的串行处理机制,脚本的运行 ...
- python学习笔记整理——集合 set
python学习整理笔记--集合 set 集合的用途:成员测试和消除重复的条目,进行集合运算 注意:花括号或set()函数可以用于创建集合. 注意:若要创建一个空的集合你必须使用set(),不能用{} ...
- [推荐]PMO学习贴大集合
[推荐]PMO学习贴大集合 http://wenku.baidu.com/view/a9b19bd4240c844769eaeed9.html http://wenku.baidu.com/view/ ...
- [置顶] Guava学习之Immutable集合
Immutable中文意思就是不可变.那为什么需要构建一个不可变的对象?原因有以下几点: 在并发程序中,使用Immutable既保证线程安全性,也大大增强了并发时的效率(跟并发锁方式相比).尤其当一个 ...
- Java学习笔记之---集合
Java学习笔记之---集合 (一)集合框架的体系结构 (二)List(列表) (1)特性 1.List中的元素是有序并且可以重复的,成为序列 2.List可以精确的控制每个元素的插入位置,并且可以删 ...
- python学习-day14:集合,函数,格式化
一.集合 定义:由不同元素组成的集合.集合是一组无序排列的可hash值, 可以作为字典的key.元素必须是不可变类型:只能存放数字,字符串,字典 特性:集合的目的是将不同的值放在一起,不同的集合之间可 ...
- 不学就吃亏的underscorejs类库学习示例 ——(集合篇)
underscorejs是一个很不错的类库,我的很多项目都引用了这个类库,的确可以带来很多方便. 记得我当初学的时候,看underscorejs的api是看的一知半解的,甚至不明白api里的conte ...
- 有关JAVA基础学习中的集合讨论
很高兴能在这里认识大家,我也是刚刚接触后端开发的学习者,相信很多朋友在学习中都会遇到很多头疼的问题,希望我们都能够把问题分享出来,把自己的学习思路整理出来,我们一起探讨一起成长. 今天我 ...
- Java学习笔记之集合
集合(Collection)(掌握) (1)集合的由来? 我们学习的是Java -- 面向对象 -- 操作很多对象 -- 存储 -- 容器(数组和StringBuffer) -- 数组而数组的长度固定 ...
- 【原】Java学习笔记026 - 集合
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 需求:从三国演义中 ...
随机推荐
- nginx配置反向代理或跳转出现400问题处理记录
午休完上班后,同事说测试站点访问接口出现400 Bad Request Request Header Or Cookie Too Large提示,心想还好是测试服务器出现问题,影响不大,不过也赶紧上 ...
- python自动化测试(2)-自动化基本技术原理
python自动化测试(2) 自动化基本技术原理 1 概述 在之前的文章里面提到过:做自动化的首要本领就是要会 透过现象看本质 ,落实到实际的IT工作中就是 透过界面看数据. 掌握上面的这样的本领 ...
- js中参数不对应问题
因为js是一种弱类型的编程语言,对数据类型的要求没有其他编程语言的要求严格,所以在定义函数的时候不需要像java和C#一样对其传入参数的类型进行定义.那么传入参数的个数有没有影响呢?今天小猪就做了个实 ...
- Winserver下的Hyper-v “未在远程桌面会话中捕获到鼠标”
异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 服务器相关的知识点:http://www.cnblogs.com/dunitia ...
- JQuery 复制粘贴上传图片插件(textarea 和 tinyMCE)
开源地址:https://github.com/yuezhongxin/paste-upload-image.js 支持 Ctrl+C/Ctrl+V 上传,支持拖拽上传,也支持 QQ/微信截图上传. ...
- 使用 Android Studio 检测内存泄漏与解决内存泄漏问题
本文在腾讯技术推文上 修改 发布. http://wetest.qq.com/lab/view/63.html?from=ads_test2_qqtips&sessionUserType=BF ...
- 高德地图api实现地址和经纬度的转换(python)
利用高德地图web服务api实现地理/逆地址编码 api使用具体方法请查看官方文档 文档网址:http://lbs.amap.com/api/webservice/guide/api/georegeo ...
- 防线修建 bzoj 2300
防线修建(1s 512MB)defense [问题描述] 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还 ...
- JVM类加载
JVM的类加载机制就是:JVM把描述类的class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被JVM直接使用的Java类型 ClassLoader JVM中的ClassLoade ...
- 【夯实Mysql基础】MySQL性能优化的21个最佳实践 和 mysql使用索引
本文地址 分享提纲: 1.为查询缓存优化你的查询 2. EXPLAIN 你的 SELECT 查询 3. 当只要一行数据时使用 LIMIT 1 4. 为搜索字段建索引 5. 在Join表的时候使用相当类 ...