话说 虽然敲过好多代码, 但除了C++,一直没正眼瞧过其它语言。(没办法 谁叫C++既有oop又能自由控制内存呢)

今天 看公司老项目的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>接口的比较器,将比较器用作有序字典的构造函数的一个参数。
 
 
包含不重复元素的集合成为“集(set)”。
.NET Framework包含两个集 HashSet<T> 和 SoredSet<T>, 它们都实现ISet<T>接口。
 
可观察的集合
如果需要集合中的元素何时删除或添加的信息,就可以使用ObservableCollection<T>类。
这个类是为WPF定义的,这样UI就可以得知集合的变化,因此这个类在程序集WindowsBase中定义;命名空间是 System.Collections.ObjectModel。
ObservableCollection<T>类派生自Collection<T>基类,该基类可以创建自定义集合,并在内部使用List<T>类。重写基类中的虚方法SetItem()和RemoveItem(),以触发CollectionChanged事件。这个类的用户可以使用INotifyCollectionChanged接口注册这个事件。
 
位数组
如果需要处理的数字有许多位,就可以使用BitArray类和BitVector32接口。
 
BitArray类
BitArray类位于名称空间System.Collections中,BitArray类可以重新设置大小,如果事先不知道需要的位数,就可以使用BitArray类,它可以包含非常多的位。
BitArray类是一个引用类型,它包含一个int数组,其中每32位使用一个新整数。
成员如下:
CountLength
Item [Get / Set]
SetAll
Not //取反
And / Or / Xor
辅助方法DisplayBits()遍历BitArray:
static void DisplayBits(BitArray bits) {
foreach (bool bit in bits) {
Console.Write(bit ? 1 : 0);
}
}
var bits = new BitArray(8); //创建一个8位的数组
bits.SetAll(true); //把8位都设置位true,即 1
bits.Set(1, false); //把下标为1的位设置为false,即 0
bits[5] = false; //使用索引器设置
Console.Write("Initialized:");
DisplayBits(bits);
Console.WriteLine();
BitVector32结构
BitVector32结构位于命名空间System.Collections.Specialized中。
BitVector32结构是基于栈的,因此比较快。但仅能包含32位,存储在一个整数中。
 
如果事先知道需要的位数,就可以使用BitVector32结构替代BitArray类,效率较高;因为他是一个值类型。
一个整数可以存储32位,如果需要更多的位,可以使用多个BitVector32值或BitArray类。
BitVector32成员如下:
Data //Data属性把BitVector32结构中的数据返回为整数
Item //BitVector32的值可以使用索引器设置
CreateMask //这是一个静态方法,用于为访问BitVector32结构中的特定位创建掩码
CreateSection //这是一个静态方法,用于创建32位中的几个片段
 
不变的集合
如果对象可以改变其状态,就很难在多个同时运行的任务中使用。这些集合必须同步。如果对象不能改变其状态,就很容易在多个线程中使用。不能改变的对象成为不变的对象。
在VS2013中,Microsoft提供了一个新的集合库: Microsoft Immutable Collections。它包含不变的集合类 ----- 创建后就不能改变的集合类。
 
并发集合
从 .NET 4开始,命名空间System.Collections.Concurrent中提供了几个线程安全的集合类。
线程安全的集合可防止多个线程以相互冲突的方式访问集合。
为了对集合进行线程安全的访问,定义了IProducerConsumerCollection<T>接口。这个接口中最重要的方法是TryAdd()和TryTake()。TryAdd()方法尝试给集合添加一项,但如果集合禁止添加项,这个操作就可能失败。TryTake()雷同。
 
下面列出System.Collections.Concurrent名称空间中的类及功能:
ConcurrentQueue<T>
ConcurrentStack<T>
ConcurrentBag<T>
ConcurrentDictionary<TKey, TValue>
BlockingCollection<T>
ConcurrentXXXX集合是线程安全的,如果某个动作不适用于线程当前状态,他们返回false。
BlockingCollection<T>是对实现IProducerConsumerCollection<T>接口的任意类的修饰器,他默认使用ConcurrentQueue<T>类。
 
创建管道
将这些并发集合类用于管道是一种很好的应用:一个任务向一个集合类写入一些内容,同时另一个任务从该集合中读取内容。
 
性能
许多集合类都提供了相同的功能,但是,其性能常常有很大的区别。
在MSDN文档中,集合的方法常常有性能提示,给出了以大写O标记的操作时间:
O(1) //表示无论集合中有多少数据项,这个操作需要的时间都不变
O(long n) //表示对于集合执行一个操作需要的事件在最坏情况是是N
O(n) //表示操作需要的时间随集合中元素的增加而增加,但每个元素需要增加的时间不是线性的,而是呈对数曲线
 
 
总结
数组Array的大小是固定的,可以使用列表List作为动态增长的集合。
队列Queue以先进先出的方式访问元素,栈Stack以先进后出的方式访问元素。
链表LinkedList可以快速的插入和删除元素,但搜索操作比较慢。
通过键值对可以使用字典Dictionary,它的搜索和插入操作比较快。
集用于唯一项,可以是无序的HashSet,也可以是有序的SortedSet。
ObservableCollection类提供了列表中的元素发生变化时触发的事件。
 

最新文章

  1. 点击切换panel
  2. [C#常用代码]类库中读取解决方案web.Config字符串
  3. 在Android上用AChartEngine轻松绘制图表
  4. hdu 1561 The more, The Better (树上背包)
  5. 哪些函数不能为virtual函数
  6. GET与POST提交
  7. 自定义 Layer 属性的动画
  8. [国嵌攻略][066][ARP协议实现]
  9. 使用XStream是实现XML与Java对象的转换(2)--别名
  10. 倒计时5S秒自动关闭弹窗
  11. 我的C#跨平台之旅(四):使用AOP(filter、attribute)进行系统增强
  12. 惰性求值——lodash源码解读
  13. “2014年CityEngine三维建模与设计精英培训班”——全国巡回举办
  14. 测试同学必备抓包工具--charles之mock数据
  15. Visualforce控制器
  16. [Codeforces Round #340 (Div. 2)]
  17. New users can not log on Win8
  18. quartz 2.0 与1.0功能对比
  19. Java 1.7 ThreadPoolExecutor源代码解析
  20. mysql数据库LOAD DATA INFILE Syntax

热门文章

  1. 攻防世界web新手练习区(2)
  2. 怎样快速高效的定义Django的序列化器
  3. Python测试进阶——(1)安装Python测试相关模块
  4. 用JS写一个网站树形菜单
  5. cenos7配置confluence+mysql5.6
  6. Day7 - D - The Euler function HDU - 2824
  7. iPad适配tabBarController
  8. maven详解之 pom.xml 解释
  9. S7-300定时器使用总结
  10. POJ 2752:Seek the Name, Seek the Fame