zoukankan      html  css  js  c++  java
  • 关于集合

    那些年你用的集合

    .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方法。

     关于SortedList<TKey,TValue>,SortedDictionary<TKey,TValue>使用出现的问题

    其键不允许重复。使用SortedSet<T>进行解决。

    参考:

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

  • 相关阅读:
    把eclipse 3.4的插件移动到独立目录中
    Crest大家都来山寨一个GObject吧
    c# 扩展方法奇思妙用性能篇一:扩展方法性能初测
    [幽默]今天看了几页c语言入门,想写个ERP, 帮我看看 技术上还差些什么?
    c# 扩展方法奇思妙用高级篇一:改进 Scottgu 的 "In" 扩展
    [个人]我的积分与排名日志
    反驳 老赵 之 “伪”递归
    c# 扩展方法奇思妙用变态篇一:由 Fibonacci 数列引出 “委托扩展” 及 “递推递归委托”
    c# 扩展方法奇思妙用高级篇五:ToString(string format) 扩展
    瑞士军刀 VS 单一职责原则
  • 原文地址:https://www.cnblogs.com/ccaa/p/12146374.html
Copyright © 2011-2022 走看看