话说 虽然敲过好多代码, 但除了C++,一直没正眼瞧过其它语言。
今天 看公司老项目的src,c#的,linq+Dictionary的用法有感。所以找来C#的资料 就学了一下,妈的 变天儿了。
以后不能再用C++编写思路,囫囵着过日子了。
------------------------------------------------------------------ 我是分割线 -----------------------------------------------------------------------
以下 学习笔记
列表List<T>、队列、栈、链表、字典和集;
位数组 和 并发集合 【多线程环境使用】
集合借口和类型
大多数集合类在System.Collections 和 System.Collections.Generic命名空间中。
泛型集合 ==> System.Collections.Generic
专用于特定类型的集合类 ==> System.Collections.Concurrent
不可变的集合类 ==> System.Collections.Immutable
列表
.NET Framework为动态列表提供了泛型类 List<T>。
这个类实现了IList、ICollection、IEnumerable、IList<T>、ICollection<T>和IEnumerable<T>接口。
ArrayList是一个非泛型列表,它可以将任意Object类型作为其元素。
使用默认的构造函数创建一个空列表。元素添加到列表中后,列表的容量就会扩大为可容纳4个元素。如果添加了第5个元素,列表的大小就成新设置为包含8个元素,如果8个元素还不够,列表的大小就重新设置为包含16个元素。每次都会将列表的容量重新设置为原来的2倍。
如果列表的内容改变了,整个集合就要重新分配到一个新的内存块中。即创建一个新的数组,大小是原来的2倍。
创建指定元素个数的列表
List<int> intList = new List<int>(10);
可以通过索引访问的集合类有 ArrayList、StringCollection 和 List<T>
ForEach()方法遍历集合中的每一项,调用作为每一项的参数传递的方法。
public delegate void Action<T> (T obj); public void ActionHandler (Racer obj); racers.ForEach( Console.WriteLine ); racers.ForEach( r => Console.WriteLine("{0:A}", r); //lambda表达式
删除元素
删除元素时,可以利用索引,也可以传递要删除的元素。
按索引删除比较快,因为必须在集合中搜索要删除的元素。Remove()方法现在集合中搜索,用IndexOf()方法获取元素的索引,在使用该索引删除元素。IndexOf()方法先检查元素类型是否实现了IEquatable<T>接口。如果是就调用这个接口的Equals()方法,确定集合中的元素是否等于传递给Equals()方法的元素。如果没有实现这个接口,就使用Object类的Equals()方法比较这些元素。Object类中的Equals()方法的默认实现代码对值类型进行比较,对引用类型只比较其引用。
重写IEquatable<T>接口或Object.Equals()方法可以根据列表元素对象的特定属性进行删除列表元素。
第7章 介绍如何重写Equals()方法
搜索
有不同的方式在集合中搜索元素。可以获得要查找的元素的引用,或者搜索元素本身。
方法有:
IndexOf() LastIndexOf() FindIndex() FindLastIndex() Find() FindLast() 检查元素是否存在:List<T>.Exists()方法;
IndexOf()可以指定不需要搜索整个集合,需要指定开始索引以及需要迭代的元素个数
FindIndex()可以搜索有某个特性的元素
public int FindIndex(Predicate<T> match); //Predicate<T>类型是一个委托,该委托返回一个bool值
int index = racers.FindIndex( r => r.Country == "FinLand");
FindIndex()方法返回所查找元素的索引。Find()方法除了获得索引之外,还可以直接获得集合中的元素。
Racer racer = racers.Find( r => r.FirstName == "Niki");
要获得于Predicate<T>类型匹配的所有项,而不是一项,可以使用FindAll()方法;
排序
List<T>类可以使用Sort()方法对元素排序。Sort()方法使用快速排序算法。
Sort()方法使用了几个重载的方法:
public void List<T>.Sort(); public void List<T>.Sort(Comparison<T>); public void List<T>.Sort(IComparer<T>); public void List<T>.Sort(Int32, Int32, IComparet<T>);
1. 只有集合中的元素实现了IComparable接口,才能使用不带参数的Sort()方法;
2. 如果需要按照元素类型不默认支持的方式排序,就应使用其他技术,如传递一个实现了IComparer<T>接口的对象。
3. 排序的另一种方式使用重载的Sort()方法。
调用Reverse()方法,逆转整个集合的顺序。
类型转换
使用List<T>类的ConvertAll<TOutput>()方法,可以把所有类型的集合转换为另一种类型。
ConvertAll<TOutput>()方法使用一个Converter委托:
public sealed delegate TOutput Converter<TInput, TOutput> (TInput from);
eg: List<Person> persons = racers.ConvertAll<Person>( r => new Person(r.FirstName + " " + r.LastName));
只读集合
List<T>集合的AsReadOnly()方法返回 ReadOnlyCollection<T>类型的对象。
ReadOnlyCollection<T>类实现的接口与List<T>集合相同,但如若修改将抛出异常NotSupportedException异常。
ReadOnlyCollection<T>还实现了IReadOnlyCollection<T>和IReadOnlyList<T>接口。
队列
Queue<T> 命名空间 System.Collections.Generic
队列是其元素以先进先出(FIFO)的方式来处理的集合。
可以使用多个队列,一个队列对应一个优先级。打印队列和线程队列是这样的。
可以为一组队列建立一个数组,数组中的一项代表一个优先级。
在内部Queue<T>类使用T类型的数组;它实现ICollection和IEnumerable<T>接口。
因为没有实现IList<T>接口,所以不能用索引器访问元素。
Queue<T>方法如下:
Count Enqueue Dequeue Peek //从队列头部读取一个元素但不删除它 TrimExcess //重新设置队列的容量,Dequeue()方法从队列中删除元素,但不会重新设置队列容量,要从队列的头部去除空元素,应使用TrimExcess()方法
多线程可以同时访问,但要是用lock语句锁定队列的访问:
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 { return documentQueue.Count > 0; } } }
栈
栈是一个后进先出(LIFO)的容器
与Queue<T>类相同,Stack<t>类实现了IEnumerable<T>和ICollection接口。
成员列表:
Count Push Pop Peek Contains
在foreach方法中,使用IEnumerable接口迭代所有的元素;栈的枚举器不会删除元素,它只是逐个返回元素
链表
LinkedList<T>是一个双向链表
链表的有点事,如果将元素插入列表的中间位置,使用链表就会非常快。
在插入一个元素时,只需要修改上一个元素的Next引用和下一个元素的Previous引用,使它们引用所插入的元素。
在List<T>类中,插入一个元素时,需要移动该元素后面的所有元素。
链表的缺点:链表的元素只能一个接一个地访问,这需要较长的时间来查找位于链表中间或尾部的元素。
有序列表
如果需要基于键对所需集合排序,就可以使用SortList<TKey, TValue>类。这个类按照键给元素排序。
字典
.NET Framework提供了几个字典类,可以使用的最主要的类是Dictionary<TKey, TValue>
键的类型
用作字典中键的类型必须重写Object类的GetHashCode()方法;字典的性能取决于GetHashCode()方法的实现代码。
除了实现GetHashCode()方法之外,键类型还必须实现IEquatable<T>.Equals()方法,或者重写Object类的Equals()方法。
Lookup 类
Lookup<TKey, TElement>把键映射到一个值集上;Lookup<TKey, TElement>类在程序集System.Core中实现,用System.Linq命名空间。
Lookup<TKey, TElement>类不能像一般的字典那样创建,而必须调用ToLookup()方法,该方法返回一个Lookup<TKey, TElement>对象。ToLookup()方法是一个扩展方法,它可以用于实现了IEnumerable<T>接口的所有类。
有序字典
SortedDictionary<TKey, TValue>类是一个二叉搜索树,其中的元素根据键来排序。该键类型必须实现IComparable<TKey>接口。
如果键的类型不能排序,则还可以创建一个实现了IComparer<TKey>接口的比较器,将比较器用作有序字典的构造函数的一个参数。
集
。。。。 未完待续