1. List

// C# 源码

public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>

{

private const int _defaultCapacity = 4;//默认容量为4

private T[] _items;//list内部是用数组实现的

[ContractPublicPropertyName("Count")]

private int _size;

private int _version;//在遍历时如果发现_version变了立即退出并抛出遍历过程集合被修改异常,比如在foreach里remove或add元素就会导致这个异常。更常见的是出现在多线程时一个线程遍历集合,另一个线程修改集合的时候,相信很多人吃过苦头。

[NonSerialized]

private Object _syncRoot;

static readonly T[]  _emptyArray = new T[0];

// 其他内容

}

// C# Code

// Adds the given object to the end of this list. The size of the list is

// increased by one. If required, the capacity of the list is doubled

// before adding the new element.

//

//扩容时翻倍

public void Add(T item) {

if (_size == _items.Length)

EnsureCapacity(_size + 1);

_items[_size++] = item;

_version++;

}

// Ensures that the capacity of this list is at least the given minimum

// value. If the currect capacity of the list is less than min, the

// capacity is increased to twice the current capacity or to min,

// whichever is larger.

private void EnsureCapacity(int min) {

if (_items.Length < min) {

int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;

// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.

// Note that this check works even when _items.Length overflowed thanks to the (uint) cast

if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;

if (newCapacity < min) newCapacity = min;

Capacity = newCapacity;

}

}

// Gets and sets the capacity of this list.  The capacity is the size of

// the internal array used to hold items.  When set, the internal

// array of the list is reallocated to the given capacity.

//

public int Capacity {

get {

Contract.Ensures(Contract.Result<int>() >= 0);

return _items.Length;

}

set {

if (value < _size) {

ThrowHelper.ThrowArgumentOutOfRangeException(

ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);

}

Contract.EndContractBlock();

if (value != _items.Length) {

if (value > 0) {

T[] newItems = new T[value];

if (_size > 0) {

Array.Copy(_items, 0, newItems, 0, _size);

}

_items = newItems;

}

else {

_items = _emptyArray;

}

}

}

}

C# 中 List默认的容量其实是4,所以最好还是初始化容量吧,可以想象,如果一个列表里面有129个元素,那么代码中对Capacity的调用会有很多次,4->8->16->32->64->128->256,不但最后的容量中产生了大量的浪费,前面的一堆对象也都需要GC搞定了。也就是252个对象。浪费还是很严重的。

// Removes the element at the given index. The size of the list is

// decreased by one.

public bool Remove(T item) {

int index = IndexOf(item);

if (index >= 0) {

RemoveAt(index);

return true;

}

return false;

}

// Returns the index of the first occurrence of a given value in a range of

// this list. The list is searched forwards from beginning to end.

// The elements of the list are compared to the given value using the

// Object.Equals method.

//

// This method uses the Array.IndexOf method to perform the

// search.

//

public int IndexOf(T item) {

Contract.Ensures(Contract.Result<int>() >= -1);

Contract.Ensures(Contract.Result<int>() < Count);

return Array.IndexOf(_items, item, 0, _size);

}

// Array.cs

public static int IndexOf<T>(T[] array, T value, int startIndex, int count) {

if (array==null) {

throw new ArgumentNullException("array");

}

if (startIndex < 0 || startIndex > array.Length ) {

throw new ArgumentOutOfRangeException("startIndex",

Environment.GetResourceString("ArgumentOutOfRange_Index"));

}

if (count < 0 || count > array.Length - startIndex) {

throw new ArgumentOutOfRangeException("count",

Environment.GetResourceString("ArgumentOutOfRange_Count"));

}

Contract.Ensures(Contract.Result<int>() < array.Length);

Contract.EndContractBlock();

return EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);

}

// Removes the element at the given index. The size of the list is

// decreased by one.

public void RemoveAt(int index) {

if ((uint)index >= (uint)_size) {

ThrowHelper.ThrowArgumentOutOfRangeException();

}

Contract.EndContractBlock();

_size--;

if (index < _size) {

Array.Copy(_items, index + 1, _items, index, _size - index);

}

_items[_size] = default(T);

_version++;

}

从代码来看,remove操作优先看的是能否找到该元素,如果能找到,将其移除,返回True,否则,返回false

C#的索引方法有点复杂,点到EqualityComparer里面看了一下索引的方法,这也是C#跟Java的不同之处了,Java的泛型里面是不能写入Primitive类型的,因为Primitive类型其实是不继承Object的,所以无法调用其中的equals方法。

但是C#是支持的,所以,会判断元类型的Type,然后选取对应的Equals方法。

现在回头看下RemoveAt方法,该方法仍然会调用Array.Copy操作,所以,可想而知删除操作的复杂度了,内存中平均删除一个元素,要移动n/2个元素,复杂度为O(n)

而RemoveAll方法本身是复杂度为O(n)的,所以最好不要在循环中写Remove操作吧。

C#List源码的更多相关文章

  1. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  2. C# ini文件操作【源码下载】

    介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...

  3. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  4. 从源码看Azkaban作业流下发过程

    上一篇零散地罗列了看源码时记录的一些类的信息,这篇完整介绍一个作业流在Azkaban中的执行过程,希望可以帮助刚刚接手Azkaban相关工作的开发.测试. 一.Azkaban简介 Azkaban作为开 ...

  5. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  6. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  7. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  8. SDWebImage源码解读之SDWebImageDownloaderOperation

    第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...

  9. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  10. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

随机推荐

  1. PAT 乙级 1092 最好吃的月饼 (20 分)

    1092 最好吃的月饼 (20 分) 月饼是久负盛名的中国传统糕点之一,自唐朝以来,已经发展出几百品种. 若想评比出一种“最好吃”的月饼,那势必在吃货界引发一场腥风血雨…… 在这里我们用数字说话,给出 ...

  2. json 中关于json数组跟json对象的区别

    原文地址:http://blog.csdn.net/lafengwnagzi/article/details/52789171 JSON 是存储和交换文本信息的语法 JSON 文本格式在语法上与创建 ...

  3. C++Primer第五版——习题答案详解(八)

    习题答案目录:https://www.cnblogs.com/Mered1th/p/10485695.html 第9章 顺序容器 练习9.1 a.list,需要按字典序插入,可能插入位置在中间 b.d ...

  4. [UE4]Native Widget Host

    一.Native Widget Host是一个容器,它可以包含一个Slate UI 二.Native Widget Host应该用在当你需要把一个Slate UI 放到UMG中的时候,只有这个时候才需 ...

  5. Java内存列表

    当jvm运行起来的时候,它会向系统申请一片内存区,并将这块内存分出一部分存储程序创建的对象,传递给方法的参数,返回值,局部变量等等,我们将这块内存称之为“运行时数据区”. 初学的时候把Java内存分为 ...

  6. 竖直的ViewPager,上下滑动的ViewPager,VerticalViewPager ;

    直接看代码吧,重写Viewpager,改变了手势和切换效果:和正常的Viewpager使用一模一样: /** * ChenboCui 竖向的Viewpager */ public class Vert ...

  7. 异常处理,MD5

    异常处理. try except raise try: 代码 except 异常类: 除了错, 如何处理异常 except 异常类: 除了错, 如何处理异常 except 异常类: 除了错, 如何处理 ...

  8. win10安装mysql一直卡在最后一步进行不下去

    新买的电脑,mysql的win10一直安装不了,一直卡在最后一步.仔细阅读下面文章解决. https://blog.csdn.net/fpga_zy/article/details/80689265

  9. !!字体图标(iconfont、Fontello 、雪碧图生成工具。Glyphicons、fontawesome 等)。 图片压缩

    http://www.iconfont.cn/  阿里巴巴矢量图标库 iconfont http://fontawesome.io fontawesome图标 http://www.bootcss.c ...

  10. ZIP压缩输入/输出流

    ZIP是压缩文件的格式,使用ZIP可以节省空间 java将压缩/解压缩文件的方法都封装在java.util.zip包下,java实现了I/O数据流和网络数据流的单一接口,所以实现起来比较容易. 主要的 ...