一. 各类数据结构比较及其线程安全问题

1. Array(数组):

  分配在连续内存中,不能随意扩展,数组中数值类型必须是一致的。数组的声明有两种形式:直接定义长度,然后赋值;直接赋值。

  缺点:插入数据慢。

  优点:性能高,数据再多性能也没有影响

  特别注意:Array不是线程安全,在多线程中需要配合锁机制来进行,如果不想使用锁,可以用ConcurrentStack这个线程安全的数组来替代Array。

 1  {2                 Console.WriteLine("---------------------------01 Array(数组)-----------------------------------");3                 //模式一:声明数组并指定长度4                 int[] array = new int[3];5                 //数组的赋值通过下标来赋值6                 for (int i = 0; i < array.Length; i++)7                 {8                     array[i] = i + 10;9                 }
10                 //数组的修改通过下标来修改
11                 array[2] = 100;
12                 //输出
13                 for (int j = 0; j < array.Length; j++)
14                 {
15                     Console.WriteLine(array[j]);
16                 }
17
18                 //模式二:直接赋值
19                 string[] array2 = new string[] { "二胖", "二狗" };
20 }

2. ArrayList(可变长度的数组)

  不必在声明的时候指定长度,即长度可变;可以存放不同的类型的元素。

  致命缺点:无论什么类型存到ArrayList中都变为object类型,使用的时候又被还原成原先的类型,所以它是类型不安全的,当值类型存入的时候,会发生装箱操作,变为object引用类型,而使用的时候,又将object类型拆箱,变为原先的值类型,这尼玛,你能忍?

  结论:不推荐使用,建议使用List代替!!

  特别注意:ArrayList不是线程安全,在多线程中需要配合锁机制来进行。

 1   {2                 Console.WriteLine("---------------------------02 ArrayList(可变长度的数组)-----------------------------------");3                 ArrayList arrayList = new ArrayList();4                 arrayList.Add("二胖");5                 arrayList.Add("马茹");6                 arrayList.Add(100);7                 for (int i = 0; i < arrayList.Count; i++)8                 {9                     Console.WriteLine(arrayList[i] + "类型为:" + arrayList[i].GetType());
10                 }
11 }

3. List<T> (泛型集合) 推荐使用

  内部采用array实现,但没有拆箱和装箱的风险,是类型安全的

  特别注意:List<T>不是线程安全,在多线程中需要配合锁机制来进行,如果不想使用锁,可以用ConcurrentBag这个线程安全的数组来替代List<T>

 1 {2                 Console.WriteLine("---------------------------03 List<T> (泛型集合)-----------------------------------");3                 List<string> arrayList = new List<string>();4                 arrayList.Add("二胖");5                 arrayList.Add("马茹");6                 arrayList.Add("大胖");7                 //修改操作8                 arrayList[2] = "葛帅";9                 //删除操作
10                 //arrayList.RemoveAt(0);
11                 for (int i = 0; i < arrayList.Count; i++)
12                 {
13                     Console.WriteLine(arrayList[i]);
14                 }
15 }

4. LinkedList<T> 链表

  在内存空间中存储的不一定是连续的,所以和数组最大的区别就是,无法用下标访问。

  优点:增加删除快,适用于经常增减节点的情况。

  缺点:无法用下标访问,查询慢,需要从头挨个找。

  特别注意:LinkedList<T>不是线程安全,在多线程中需要配合锁机制来进行。

{Console.WriteLine("---------------------------04 ListLink<T> 链表-----------------------------------");LinkedList<string> linkedList = new LinkedList<string>();linkedList.AddFirst("二胖");linkedList.AddLast("马茹");var node1 = linkedList.Find("二胖");linkedList.AddAfter(node1, "三胖");//删除操作linkedList.Remove(node1);//查询操作foreach (var item in linkedList){Console.WriteLine(item);}
}

5. Queue<T> 队列

  先进先出,入队(Enqueue)和出队(Dequeue)两个操作

  特别注意:Queue<T>不是线程安全,在多线程中需要配合锁机制来进行,如果不想使用锁,线程安全的队列为 ConcurrentQueue。

  实际应用场景:利用队列解决高并发问题(详见:http://www.cnblogs.com/yaopengfei/p/8322016.html)

 1  {2                 Console.WriteLine("---------------------------05 Queue<T> 队列-----------------------------------");3                 Queue<int> quereList = new Queue<int>();4                 //入队操作5                 for (int i = 0; i < 10; i++)6                 {7                     quereList.Enqueue(i + 100);8                 }9                 //出队操作
10                 while (quereList.Count != 0)
11                 {
12                     Console.WriteLine(quereList.Dequeue());
13                 }
14 }

6. Stack<T> 栈

  后进先出,入栈(push)和出栈(pop)两个操作

  特别注意:Stack<T>不是线程安全

 1  {2                 Console.WriteLine("---------------------------06 Stack<T> 栈-----------------------------------");3                 Stack<int> stackList = new Stack<int>();4                 //入栈操作5                 for (int i = 0; i < 10; i++)6                 {7                     stackList.Push(i + 100);8                 }9                 //出栈操作
10                 while (stackList.Count != 0)
11                 {
12                     Console.WriteLine(stackList.Pop());
13                 }
14 }

7. Hashtable

  典型的空间换时间,存储数据不能太多,但增删改查速度非常快。

  特别注意:Hashtable是线程安全的,不需要配合锁使用。

{Console.WriteLine("---------------------------07 Hashtable-----------------------------------");Hashtable tableList = new Hashtable();//存储tableList.Add("001", "马茹");tableList["002"] = "二胖";//查询foreach (DictionaryEntry item in tableList){Console.WriteLine("key:{0},value:{1}", item.Key.ToString(), item.Value.ToString());}
}

8. Dictionary<K,T>字典 (泛型的Hashtable)

  增删改查速度非常快,可以用来代替实体只有id和另一个属性的时候,大幅度提升效率。

  特别注意:Dictionary<K,T>不是线程安全,在多线程中需要配合锁机制来进行,如果不想使用锁,线程安全的字典为 ConcurrentDictionary。

 1  {2                 Console.WriteLine("---------------------------08 Dictionary<K,T>字典-----------------------------------");3                 Dictionary<string, string> tableList = new Dictionary<string, string>();4                 //存储5                 tableList.Add("001", "马茹");6                 tableList.Add("002", "二胖");7                 tableList["002"] = "三胖";8                 //查询9                 foreach (var item in tableList)
10                 {
11                     Console.WriteLine("key:{0},value:{1}", item.Key.ToString(), item.Value.ToString());
12                 }
13 }

强调: 

以上8种类型,除了Hashtable是线程安全,其余都不是,都需要配合lock锁来进行,或者采用 ConcurrentXXX来替代。

详细的请见:http://www.cnblogs.com/yaopengfei/p/8322016.html

二. 四大接口比较

1. IEnumerable

  是最基本的一个接口,用于迭代使用,里面有GetEnumerator方法。

2. ICollection

  继承了IEnumerable接口,主要用于集合,内部有Count属性表示个数,像ArrayList、List、LinkedList均实现了该接口。

3. IList

  继承了IEnumerable 和 ICollection,实现IList接口的数据接口可以使用索引访问,表示在内存上是连续分配的,比如Array、List。

4. IQueryable

  这里主要和IEnumerable接口进行对比。

  Enumerable里实现方法的参数是Func委托,Queryable里实现的方法的参数是Expression表达式。

  实现IQueryable和IEnumabler均为延迟加载,但二者的实现方式不同,前者为迭代器模式,参数为Func委托,后者为Expression表达式目录树实现。

三. yield关键字

1. yield必须出现在IEunmerable中

2. yield是迭代器的状态机,能做到延迟查询,使用的时候才查询,可以实现按序加载

3. 例子

  测试一:在 “var data1 = y.yieldWay();”加一个断点,发现直接跳过,不能进入yieldWay方法中,而在“foreach (var item in data1)”加一个断点,第一次遍历的时候就进入了yieldWay方法中,说明了yield是延迟加载的,只有使用的时候才查询。

  测试二:对yieldWay和commonWay获取的数据进行遍历,通过控制台发现前者是一个一个输出,而后者是先一次性获取完,一下全部输出来,证明了yield可以做到按需加载,可以在foreach中加一个限制,比如该数据不满足>100就不输出。

 View Code

 1             Console.WriteLine("-----------------------下面是调用yield方法-----------------------");2             yieldDemo y = new yieldDemo();3             var data1 = y.yieldWay();4             foreach (var item in data1)5             {6                 Console.WriteLine(item);7             }8             Console.WriteLine("-----------------------下面是调用普通方法-----------------------");9             var data2 = y.commonWay();
10             foreach (var item in data2)
11             {
12                 Console.WriteLine(item);
13             }

第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字相关推荐

  1. 深度剖析Java数据结构之迭代器(Iterator)

    一.什么是迭代器 我们知道,JVM是用C/C++编写的.在百度百科中,迭代器是解释是迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定 ...

  2. 深度剖析Java数据结构之表(三)——ArrayList泛型类的实现

    为了避免与类库中的ArrayList类重复,在这里,使用的类名为ArrayListDemo.在Java中,ArrayList泛型类是继承AbstractList泛型类的,并且实现了List<E& ...

  3. 深度剖析Java数据结构之队列(一)——双端队列(ArrayDeque)

    一.队列 队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作.进行插入操作的端称为队尾,进行删除操作的端称为队头.队列中没有元素时,称为空队列. ...

  4. 深度剖析Java数据结构之表(四)——LinkedList泛型类的实现

    在Java中,LinkedList泛型类继承了AbstractSequentialListf泛型类,实现了List.Deque.Colneable和Serializable接口,定义如下: 该类的实现 ...

  5. 深度剖析Java数据结构之表(二)——List接口

    一.List接口 在Java中,List接口的定义如下: public interface List<E> extends Collection<E> { int size() ...

  6. 布隆过滤器原理深度剖析

    HBase布隆过滤器原理深度剖析 1. 数据结构与原理 1.1 初始化 1.2 变量映射 1.3 变量检索 1.4 总结 2. 过滤器特性 2.1 误判率 2.2 判断特点 3. 案列代码 1970年 ...

  7. 《AngularJS深度剖析与最佳实践》一1.4 实现第一个页面:注册

    本节书摘来自华章出版社<AngularJS深度剖析与最佳实践>一书中的第1章,第1.4节,作者 雪狼 破狼 彭洪伟,更多章节内容可以访问云栖社区"华章计算机"公众号查看 ...

  8. 网页***深度剖析以及手工清除

    阅读提示:杀毒软件风靡全球的今天,各式各样的病毒仍然在网络上横行,其形式的多样化,自身之隐蔽性都大大的提高.其中,网页病毒.网页***就是这个新型病毒大军中危害面最广泛,传播效果最佳的.之所以会出此篇 ...

  9. 网页***深度剖析以及手工清除的方法

    前 言   杀毒软件风靡全球的今天,各式各样的病毒仍然在网络上横行,其形式的多样化,自身之隐蔽性都大大的提高.其中,网页病毒.网页***就是这个新型病毒大军中危害面最广泛,传播效果最佳的.之所以会出此 ...

最新文章

  1. java图片序列化_Java中的强大武器——对象的序列化
  2. stm32怎么用keil软件进行仿真?(必需掌握的技能)
  3. Spring Framework 5.2 正式发布,14项新特性一览
  4. 我国火力发电站的大脑用上了国产系统
  5. MSP430F5529 DriverLib 库函数学习笔记(十二)I2C实战
  6. python递归算法案例教案_python教案
  7. open×××+Mysql+PAM构建强大的***系统
  8. 作业 输出演练 1751
  9. PL/SQL Developer自动补全SQL技巧
  10. 项目IDEA启动配置
  11. plsql导出表结构和表数据的使用小结
  12. ubuntu20.04安装nvidia显卡驱动/CUDA/cuDNN
  13. Linux|操作系统
  14. mac网易邮箱smtp服务器,网易企业邮箱MAC mail客户端设置
  15. js校验图片是否加载成功或失败
  16. 未来财富:呼啸而来的数字人民币
  17. arthas的监控java性能
  18. scilab安装EMD工具箱
  19. 我见过最全的剖析QEMU原理的文章[Z]
  20. Mac iterm2 中文乱码

热门文章

  1. 第四周读书笔记《构建之法》
  2. Ubuntu 16.04 设置MySQL远程访问权限
  3. 洛谷 P1852 奇怪的字符串
  4. 题目1065:输出梯形
  5. 《avascript 高级程序设计(第三版)》 ---第三章 基本概念
  6. O-C相关-08-动态类型与静态类型
  7. 打印机打印第一页的问题
  8. 【转】 ADO.NET最佳实践
  9. 120. Triangle
  10. 847. Shortest Path Visiting All Nodes(一)