关于集合

Posted ccaa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于集合相关的知识,希望对你有一定的参考价值。

那些年你用的集合

.NET有超过20种内置的集合类型,.NET Framework中有些集合只是为了保持向后兼容性,新的代码种绝不应该再去使用以下集合

ArrayList

Hashtable

Queue

SortedList

Stack

ListDictionary

HybridDictionary

为啥呢?因为会发生类型转换和装箱操作。,上述集合类保存的都是对Object实例的引用,所以你总要转换未实际的对象类型,装箱是最严重的问题。

试着用这些集合

1:假设访问有一个Int32类型的ArrayList,每个成员都会单独装箱并保存在内存堆中,为了访问所有的Int32成员,并不是像对联系存放的内存数组那样遍历,而是需要对每个引用进行一次指针间接引用,再访问内存堆(丧失了就近访问可能性),在进行一次拆箱操作获取内部的数据值。所以下面可替换为

ArrayList List<T>
CaseInsensitiveComparer StringComparer.OrdinalIgnoreCase
CaseInsensitiveHashCodeProvider StringComparer.OrdinalIgnoreCase
CollectionBase Collection<T>
Comparer Comparer<T>
DictionaryBase Dictionary<TKey, TValue> 要么 KeyedCollection<TKey, TItem>
DictionaryEntry KeyValuePair<TKey, TValue>
Hashtable Dictionary<TKey, TValue>
Queue Queue<T>
ReadOnlyCollectionBase ReadOnlyCollection<T>
SortedList SortedList<TKey, TValue>
Stack Stack<T>

Dictionary实现为一个哈希表,插入和读取 操作的时间复杂度为O(1)

SortedDictionary实现为二叉树,插入和读取操作的时间复杂度为O(log n)

SortedList实现为有序数组,读取操作的时间为O(log n),最坏为O(n),内存需求最少,

HashSet 使用了哈希表,插入和删除操作O(1)

SortedSet使用了二叉树,插入和删除操作O(log n)

List,StarcK,Queue在内部都使用了数组,操作数据量大的时候效率较高,事先如果知道成员的大小,应该把所需的内存预先分配好,这样是避免CPU和GC开销去调整数组的大小。

并发访问的集合类

 

System.Collections.Concurrent命名空间

ConcurrentBag<T>

ConcurrentDictionary<TKey,TValue>

ConcurrentQueue<T>

ConcurrentStack<T>

......

大部分内容使用了Interlocked或Monitor作为同步原语

 以上需要注意

TryXXX方法,但当其他线程正在操作而发生冲突时,就会失败

如ConcurrentStarkTryPop当其他线程正在操作而发生冲突时,就会返回false,

ConcurrentDictionary可调用TryAdd,或者用TryUpdate。

AddOrUpdate不能直接给出新数据,而是需要传入两个委托,分别用于添加和修改操作.

第一个委托,键不存在,返回对应的值

第二个委托,键存在,返回新值或已存在的值

其实不管键存在不存在,都会返回新值,你需要明白一个新值可能并非来自当前线程发起的AddOrUpdate调用,这些方法是线性安全的,但不是原子性,可能其他线程用同一个键调用了方法,第一个线程返回了第二个线程返回的值。

 为啥不直接传入数据,而用委托,因为很多时候给的键生成值是一件开销很大的操作,你不希望两个线程同时进行这种操作,委托可以让你使用现有的数据,而不是在生成一份新的拷贝。委托不一定只会调用一次,如果要保证添加和修改的同步性,还需要在委托中添加同步代码。

1:SortedDictionary<TKey,TValue> 类

表示根据键进行排序的键/值对的集合。

比较:泛型类是具有 O (log n)检索的二进制搜索树,其中 n 是字典中的元素数。 在这方面,它类似SortedList<TKey,TValue>于泛型类。 这两个类具有相似的对象模型,两者都有 O (log n)检索。 这两个类的不同之处在于内存使用和插入和删除的速度:

使用TryGetValue方法作为更高效的方法来检索值,如果程序必须经常尝试在已排序的列表中,不必显示如何使用ContainsKey方法来测试某个键是否存在之前调用Add方法。

 

参考:

https://github.com/dotnet/platform-compat/blob/master/docs/DE0006.md

以上是关于关于集合的主要内容,如果未能解决你的问题,请参考以下文章

关于代码片段的时间复杂度

金蝶handler中 collection 代码片段理解

Alfred常见使用

关于片段生命周期

比较 C# 中的字符串片段并从集合中删除项目

关于js----------------分享前端开发常用代码片段