.Net有两类基础的集合类型:List和Dictionary。List是基于Index的,Dictionary是基于key的。集合类型一般实现了IEnumberable,ICollection或者Ilist
    接口。

    类型

    描写叙述

    使用场景

    ArrayList

    可以依据加入项动态调整集合大小。

      • 适用于存储自己定义类型,特别是对于数据常常进行添加和删除的。
      • 使用TrimToSize()去掉预留元素位置,优化性能。

      • 使用ArrayList.BinarySearch进行高效的查询。
      • 不要用ArrayList去存储string。用StringCollection取代。
      • ArrayList.Sort()默认使用的是高速排序。

    Hashtable

    基于Key的hash值。存储key/value对的collection类型。

      • 适用于存储大量并不常常更改的数据,数据常常修改会造成额外的性能开销(计算hash值)。

      • 适用于常常Search而不须要排序的情况。

    HybridDictionary

    可以依据集合的大小,动态使用对应类型的字典类型。使用ListDictionary(小)。使用Hashtable(大)。

      • 适用于常常进行Search操作。

      • 不要用于排序。

    ListDictionary

    基于Key的hash值,存储key/value对的collection类型,基于单链表实现的。

      • 对于不大于10的key/value对的排序很高效。

    NameValueCollection

    存储string类型的key/value的可排序的Collection。

      • string类型。可排序。能够在一个集合中包括多个同样Key的实体。
      • 适用于常常改变数据。
      • 适用于去缓存数据项以便于高速取回。

    SortedList

    基于Key排序的Key/value对的collection。能够通过key或index来提取value。

      • 适用于存储静态数据,而且在一段时间内仅仅有少量数据须要更新。
      • 能够用于高速依据索引或者Key来取回数据。
      • 避免用于存储数据有大量更新的数据。创建和排序的时间很耗时。
      • 避免存储string类型。由于过度的转换开销。使用StringCollection
        取代。

    StringCollection

    string类型的arraylist

      • 适用于存储常常变化的string类型的数据,而且须要在大块中检索。
      • 适合绑定string类型数据到DataGrid,避免了向下类型转换的开销。

    StringDictionary

    基于Hash table。

    用于存储key是string类型的Dictionary

      • 适用于存储须要常常检索的静态string类型数据

    Queue

    基于ICollection的实现。先进先出

    Stack

    后进先出

    集合类型常见问题:

    • Boxing issues
    • Thread safety
    • Enumeration overhead

     Boxing issues

    假设使用ArrayList去存储值类型时都会被运行装箱操作。当取数据时会运行拆箱操作。

    当要存储大量的item时会导致过度开销。

    ArrayList al =
    new ArrayList();

    for (int i = 0; i < 1000; i++)

    al.Add(i);
    //Implicitly boxed because Add() takes an object

    int f = (int)al[0];
    // The element is unboxed

    解决方式:

    考虑使用强类型的数组取代。或者使用自己定义集合类型。

    在.net framework 2.0之后,使用泛型能够避免装箱和拆箱的开销。

     Thread Safety

    通常,集合默认不是线程安全的。在多线程下对于读操作是线程安全的,对于不论什么改动操作是非线程安全的,会导致未知的结果。

    解决方式:

    1. 使用Synchronized方法

    //初始化

    ArrayList arrayList = new ArrayList();

    //加入对象到集合

    …….

    //使用Synchronized方法

    Arraylist syncArrayList = ArrayList.Synchronized(arrayList);

    1. 使用Lock语句的SyncRoot属性

    ArrayList myCollection = new ArrayList();

    Lock(myCollection.SyncRoot){}

     Enumeration Overhead

    .Net Framework 1.1
    通过重写IEnumerable.GetEnumberator
    方法提供了枚举器。

    但也不是非常理想,理由例如以下:

    • GetEnumerator方法是虚拟的,所以无法内联。

    • GetEnumerator方法返回的是Ienumerator的接口而不是一个实际的类型。因此,在编译期间,无法确定实际的枚举器(Enumerator)
    • MoveNext方法和Current属性相同是虚拟的,因此无法内联。
    • IEnumerator.Current返回的的是Object类型。依据存储在集合的数据类型可能须要装箱和拆箱操作。

    因此在使用foreach对集合进行操作时会面临托管堆和虚拟方法的开销。

     Collection Guidelines

    • Analyze your requirements before choosing the collection type.(选择集合类型之前进行需求分析)
    • Initialize collections to the right size when you can.(当你能确定集合的大小时,初始化集合时指定合适的大小)
    • Consider enumerating overhead.(考虑枚举开销)
    • Prefer to implement IEnumerable with optimistic concurrency.(实现IEnumerable接口去实现开放式并发)
    • Consider boxing overhead.(考虑装箱和拆箱开销)
    • Consider for instead of foreach.(考虑使用for取代foreach)
    • Implement strongly typed collections to prevent casting overhead.(实现强类型的集合类型去防止强制转换开销)
    • Be efficient with data in collections.(高效利用集合中的数据)

    Analyze your requirements before choosing the collection type.

    • Do you need to sort your collection?

      • ArrayList适用于仅仅读已排序的数据作为数据源
      • SortedList适用于须要排序的静态不常常更新的数据,通常。(当构造集合时SortedList预先排序数据,创建排序列举的过程是比較昂贵的。可是不论什么对数据的更新都能自己主动且高效的对集合进行又一次排序)
      • NameValueCollection适用于须要排序的字符串集合。

    • Do you need to search your collection?

      • 假设你会依据key/value随机的进行search,使用HashTable。

      • 假设对字符串进行随机的search,使用StringDictionary。

      • 对于集合大小小于10的进行search使用ListDictonary
    • Do you need to access each element by index?

      • 对于基于0索引開始的集合。使用ArrayList和StringCollection
      • 通过Key来取数据,使用HashTable,SortedList,ListDictionary,StringDictionary。
      • NameValueCollection既能够使用索引又能够通过key取数据。
      • 集合(Array)通过索引取数据比不论什么集合类型都高效。

    • Do you need a custom collection?

      • 当你想通过引用类型封送集合。
      • 你须要创建一个强类型集合来避免转换开销(假设创建的强类型集合是继承自CollectionBase
        或者Hashtable。你依然无法避免转换开销。)。

      • 你须要创建一个仅仅读集合。

      • 你须要对你的强类型集合提供序列化。
      • 你须要注意枚举的开销。

    Initialize collections to the right size when you can.

    • 尽可能的指定集合的大小,能够更好的提高集合性能。

    Consider enumerating overhead.

    • 假设实现了Ienumerable.GetEnumerator,同一时候实现一个非虚拟的GetEnumerator方法。

    class MyClass : IEnumerable

    {

    // non-virtual implementation for your custom collection

    public MyEnumerator GetEnumerator() {

    return new MyEnumerator(this); // Return nested public struct

    }

    // IEnumerator implementation

    public IEnumerator.GetEnumerator() {

    return GetEnumerator();//call the non-interface method

    }

    }

    foreach调用非虚拟的GetEnumerator会比通过接口调用虚拟方法更高效。

    • 实现IEnumerator.Current属性。

    // Custom property in your class

    //call this property to avoid the boxing or casting overhead

    Public MyValueType Current {

    MyValueType obj = new MyValueType();

    // the obj fields are populated here

    return obj;

    }

    // Explicit member implementation

    Object IEnumerator.Current {

    get { return Current} // Call the non-interface property to avoid casting

    }

    Prefer to implement IEnumerable with optimistic concurrency.

    • 确保集合不会被改动当集合正在被枚举。
    • 採用快照在枚举器中。

    Consider boxing overhead.

    当在集合中存储值类型时,装箱开销会依据集合的大小。更新或操作数据的频率影响。

    假设不须要集合过多的功能,尽量使用Array.

    Consider for instead of foreach.

    在性能敏感的代码中尽量使用for.

    Implement strongly typed collections to prevent casting overhead.

    Be efficient with data in collections.

    当处理大量的对象时。处理每一个对象的大小会十分重要。



Collections你用对了吗?的更多相关文章

  1. Java基础Map接口+Collections工具类

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  2. Java基础Map接口+Collections

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  3. 计算机程序的思维逻辑 (54) - 剖析Collections - 设计模式

    上节我们提到,类Collections中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了第一类,本节我们介绍第二类. 第二类方法大概可以分为两组: 接受其他 ...

  4. 2DToolkit官方文档中文版打地鼠教程(三):Sprite Collections 精灵集合

    这是2DToolkit官方文档中 Whack a Mole 打地鼠教程的译文,为了减少文中过多重复操作的翻译,以及一些无必要的句子,这里我假设你有Unity的基础知识(例如了解如何新建Sprite等) ...

  5. 计算机程序的思维逻辑 (53) - 剖析Collections - 算法

    之前几节介绍了各种具体容器类和抽象容器类,上节我们提到,Java中有一个类Collections,提供了很多针对容器接口的通用功能,这些功能都是以静态方法的方式提供的. 都有哪些功能呢?大概可以分为两 ...

  6. Collection和Collections的区别?

    Collection 是接口(Interface),是集合类的上层接口. Collections是类(Class),集合操作的工具类,服务于Collection框架.它是一个算法类,提供一系列静态方法 ...

  7. Collections.shuffle

    1.Collections.shuffler 最近有个需求是生成十万级至百万级的所有随机数,最简单的思路是一个个生成,生成新的时候排重,但是这样时间复杂度是o(n^2),网上看了几个博客的解决方法都不 ...

  8. 集合工具类:collections

    collection与collections的关系? public class Collectionsextends Object collection与collections没有直接的关系,但是与集 ...

  9. Map集合及与Collection的区别、HashMap和HashTable的区别、Collections、

    特点:将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值. Map集合和Collection集合的区别 Map集合:成对出现 (情侣)                       ...

  10. python collections模块

    collections模块基本介绍 collections在通用的容器dict,list,set和tuple之上提供了几个可选的数据类型 namedtuple() factory function f ...

随机推荐

  1. [Unit Testing] Directive testing, require parent controller

    function getCompiledElement() { $scope.chart = { additional: "$ 1.56 / per minute", text: ...

  2. python-布尔值

    布尔只有两个值:0,1 1或0 真或假 下面的值在作为布尔表达式的时候,会被解释器看作假(false) False    None    0   ""    ()    []   ...

  3. Android-------手机屏幕适配之文件适配

    public class Main {         //定义文件本地存储路径,可按照需求更改         private final static String rootPath = &quo ...

  4. CSS属性值定义语法中的符号说名

    我们通常看到一个CSS语法,总是有很多符号在其中,这些符号是什么鬼呢,且看下面道来 这些符号可以大致分为2类:分组类与数量类. 1.分组类,就是分成一堆一堆啦: 符号 名称 描述 示例   并置 各部 ...

  5. https://github.com/aptana/studio3/releases aptana

    https://github.com/aptana/studio3/releases  aptana

  6. 【04】基础:将采集结果转成Excel

    前面的教程说了,数据抓取完毕之后,数据以xml格式的形式存储在本地文件夹中. 下面简单地说一下如何将保存在本地的XML文件转成Excel格式. 第一步:压缩文件 进入本地DataScraperWork ...

  7. 使用jekyll和prose在github上创建博客

    利用github的pages服务可以很方便地显示和管理我们的静态页面,这样用来做博客是非常适合的. 1.首先你要有一个github的帐号 2.创建一个repo,名字叫username.github.i ...

  8. 理解Python中的装饰器

    文章先由stackoverflow上面的一个问题引起吧,如果使用如下的代码: @makebold @makeitalic def say(): return "Hello" 打印出 ...

  9. php 解决乱码的通用方法

    一,出现乱码的原因分析 1,保存文件时候,文件有自己的文件编码,就是汉字,或者其他国语言,以什么编码来存储 2,输出的时候,要给内容指定编码,如以网页的形势输入时<meta http-equiv ...

  10. NOI十连测 第六测 T3

    思路:考试的时候我非常地**,写了圆并,然后还TM写了半平面交和三角剖分,虽然只有30分..但是看在我写了500行的份上还是挂着吧.. #include<cstdio> #include& ...