一,数组 Array
特点:
数组存储在连续的内存上;数组的内容类型都相同;数组可以通过下面进行直接访问;
创建过程:
创建一个新的数组时将在CLR托管堆中分配一块连续的内存空间来存放数量为size,类型为所声明类型的数组元素,如果类型为值类型,则将会有size个未装箱的该类型的值被创建,如果是引用类型,将会有size个相应类型的引用被创建;
携带方法: 略
优劣:
由于内存连续,所以索引速度非常快,访问一个元素的速度与元素的数量无关,且赋值和修改都非常简单;
同样,由于内存连续且声明的时的长度是固定的,在插入新元素和长度初始声明时会存在风险;
拓展1:装箱和拆箱
基础知识:
值类型在栈中分配内存,在声明初始化才能使用,且不能为null;值类型超出作用范围系统自动释放内存;主要由结构(整型,浮点型,decimal,bool,用户自定义struct结构)和 枚举(enum)组成;
引用类型在堆中分配内存,初始化时默认为null;引用类型是通过垃圾回收机制进行回收;包括类,接口,委托,数组以及内置的引用类型object和string;
事件原因:
由于c#中所有的数据类型都是由基类System.Object继承而来,所以,值类型和引用类型的值是可以通过显式或隐式操作来相互转换,而这个过程就是装箱(boxing)和拆箱(unboxing)过程;
装箱:
装箱是 值类型 到object类型 或 到此值类型所实现的任何接口的隐式转换(转为接口依旧要装箱);对值类型装箱会在堆中分配一个对象实例,并将该值复制到新的对象中;
拆箱:
拆箱是 object类型到值类型 或 从接口类型到实现该接口的值类型的显示转换;
取消拆箱:
检查对象实例,确保它是给定值类型的一个装箱值(拆箱后没有转成原类型,编译时不会出错,但是运行会出错;用GetType.ToString()判断时一定要使用类型全称,如System.String 替换掉 String);
将该值从实例赋值到值类型变量中;
频繁的装箱和拆箱对性能的影响很大;故手动的操作很重要
二,ArrayList
特点:
消除了数组创建时必须指定长度所带来的风险;它属于System.Collections命名空间下的一部分;
可以存储不同类型的元素(元素会都会统一当成Object来处理 => 加入不同类型元素是被允许的);
创建过程:
ArrayList arryListname = new ArrayList();
携带方法:略
优劣:
由于ArrayList把不同的类型都当成Objec来处理
=>所以很可能在使用时发生类型不匹配问题,所以,ArrayList不是类型安全的;
=>会不断的装箱;时间损耗同时也会效率降低
三,List<T> 泛型List
特点:
长度可以灵活改变;
内部实际是Array来实现的;
创建过程:
List <string> stringList = new List<string>();
携带方法:略
优劣:
保证了类型安全; 取消了装箱和拆箱的操作;融合了ArrayList的长度自由变化;
四,LinkedList<T> 链表
特点:
链表在内存存储傻的排序上可能是不连续的;
链表是通过上一个元素指向下一个元素来排序,不能通过下标来访问;
不用动态扩充长度;
创建过程:
LinkedList<string> myLinkedList = new LinkedList<string>();
携带方法: 略
优劣:
由于内存存储的不一定连续性,访问无法通过下标,必须从开始节点开始遍历,逐次遍历下一个节点直到找到目标,所以查找方面无法与Array相比;
由于没有连续内存存储,所以在增减节点(插入删除)操作上很便利;
链表适合元素数量不稳定且经常操作两端来增减节点的情况;
五,Queue<T> 队列
特点:
一种先入先被删除(first in first out)的线性表;
默认情况下,初始容量为32;增长因子为 2.0, 使用TrimExcess来降低容量;
加入元素时,将通过又一次分配内部数组来依据须要自己主动增大容量;
能接受null作为有效值,并且允许重复的元素;
创建过程:
Queue<int> q = new Queue<int>();
携带方法:
q.Enqueue(1); q.Enqueue(2); q.Enqueue(3); q.Enqueue(4); //依次放入1,2,3,4
q.Count(); //返回队列中元素的数量
q.Dequeue(); //取出排在第一的元素, 队列中只剩下2,3,4
q.Peek(); //查看队列中的第一元素, 只是查看,没有取出, 队列中还有2,3,4
foreach(int y in q) { cw{y}}; //遍历查看队列中的元素
q.TrimExcess();重置队列容量(将容量设置为队列中元素的实际数目)
....
注意:
若要区分空值和 Queue 结尾,请检查 Count 属性或捕捉 Queue 为空时引发的 InvalidOperationException异常;
六,Stack<T>
特点:
一种先入后出(first in last out)的线性表;默认情况下;
增长因子为 2.0, 使用TrimExcess来降低容量;
加入元素时,将通过又一次分配内部数组来依据须要自己主动增大容量;
能接受null作为有效值,并且允许重复的元素;
创建过程:
Stack<T> s = new Stack<T>():
携带方法:
Puch(); //添加一个值到集合顶部
Pop(); //删除一个顶部一个值
Peek(); //查看顶部值
...
七,Dictionary<K,T>
特点:
元素为键值对,键必须唯一,键值都可以是任何类型;通过键读取一个值的时间复杂度为O(1);
内部维持的是两个数组;
创建过程:
Dictionary<K, T> D = new Dictionary<K, T>();
携带方法:
Add(“a”,“aa”); //添加字符串结构
D["a"]; //取值,得到aa
D["a"] = ''bb"; //修改key为a的值为“bb”
D.Remove("a"); //删除元素
D.ContainsKey("a"); //判断key是否存在
foreach (string key in D.Keys){ Console.WriteLine("Key = {0}", key);} //遍历key
foreach (string key in D.Values){ Console.WriteLine("Key = {0}", key);} //遍历value
foreach (KeyValuePair<string, string> kvp in D){Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);} //遍历字典
...
注意:
空间换时间的字典,啥都能刚!
结论:
Array 需要处理的元素数量确定并且需要使用下标时可以考虑,不过建议使用List<T>
ArrayList 不推荐使用,建议用List<T>
List<T>泛型List 需要处理的元素数量不确定时 通常建议使用
LinkedList<T> 链表适合元素数量不固定,需要经常增减节点的情况,2端都可以增减
Queue<T> 先进先出的情况
Stack<T> 后进先出的情况
Dictionary<K,T> 需要键值对,快速操作
网友评论