.NET面试题系列(五)数据结构(Array、List、Queue、Stack)及线程安全问题

集合

1. Array(数组):

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

  缺点:插入数据慢。

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

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

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

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

    致命缺点:无论什么类型存到ArrayList中都变为object类型,使用的时候又被还原成原先的类型,所以它是类型不安全的,当值类型存入的时候,

      会发生装箱操作, 变为object引用类型,而使用的时候,又将object类型拆箱,变为原先的值类型,这尼玛,你能忍?

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

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

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

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

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

4. LinkedList<T> 链表

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

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

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

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

5. Queue<T> 队列

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

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

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

6. Stack<T> 栈

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

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

7. Hashtable

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

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

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

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

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

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

四大接口

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是迭代器的状态机,能做到延迟查询,使用的时候才查询,可以实现按序加载

猜你喜欢

转载自www.cnblogs.com/cnki/p/9248929.html