雪千渔Blog

  • 首页
  • Coding
    • dotNet
    • C++
    • Lua
    • Visual Basic
    • Java
    • Android
    • Web
  • DCC
    • Maya
    • Maya-Plug
    • AfterEffect
    • AfterEffect-Plug
    • PhotoShop-Plug
  • GameDev
    • Unity3D
    • UnrealEngine
    • 经验杂谈
    • 游戏设计
    • 自研引擎
    • 效果实现
  • Graphics
    • OpenGL
    • Vulkan
    • 计算机图形学
  • 其他
    • 乱七八糟
    • 软件工具
    • 留言板
    • 自制素材
    • 关于我
雪千渔blog
唯有热爱,能抵漫长岁月
  1. 首页
  2. Coding
  3. dotNet
  4. 正文

ArrayList与List的解析

2020年2月7日 5602点热度 1人点赞 0条评论

在程序编写过程中List的使用频率是相当之高,高过了数组,和Dictionary并起成为dotNet中的两大容器,但也只是会用而已,并不清楚具体的原理,早期我认为List内部是由链表实现的,但实际上并不是那样,本次查看了源码,对常用的基础容易有一定的了解。因ArrayList和List基本相同,所以先对ArrayList剖析,再来对比与List的不同。 数组在声明时就需要确认长度以便申请内存,在内存中是连续并且长度是固定的,索引速度上肯定是最快的,赋值与修改也非常简单,但因长度固定,插入和删除是个比较麻烦的事情,为此诞生了容器类ArrayList。 System.Collections命名空间下ArrayList类

private object[] _items;
private int _size;

在ArrayList类中有两个字段,_items为该类维护的数组,_size计数(注:数组元素为object类型)

public virtual int Count
{
    get
    {
        return this._size;
    }
}

获取ArrayList中元素的数量,返回的也就是维护的_size字段

public virtual int Add(object value)
{
    //如果元素数量等于数组长度
    if (this._size == this._items.Length)
    {
        //增加数组长度
        this.EnsureCapacity(this._size + 1);
    }
    //元素赋值
    this._items[this._size] = value;
    this._version++;
    //计数增加
    int size = this._size;
    this._size = size + 1;
    return size;
}

private void EnsureCapacity(int min)
{
    if (this._items.Length < min)
    {
        //如果数组是空的,分配4个元素的长度,否则申请多一倍的长度
        int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
        if (num > 2146435071)
        {
            num = 2146435071;
        }
        if (num < min)
        {
            num = min;
        }
        this.Capacity = num;
    }
}

public virtual int Capacity
{
    get
    {
        return this._items.Length;
    }
    set
    {
        if (value < this._size)
        {
            throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
        }
        if (value != this._items.Length)
        {
            if (value > 0)
            {
                //在托管堆内存中重新建立一个数组,并把旧数组的内容复制到新数组中
                object[] array = new object[value];
                if (this._size > 0)
                {
                    Array.Copy(this._items, 0, array, 0, this._size);
                }
                this._items = array;
                return;
            }
            //空数组分配4个长度
            this._items = new object[4];
        }
    }
}

由此可见,当ArrayList第一次插入数据的时候,会默认分配4个元素长度的空间,如果超出4个则重新建立数组,复制旧数组数据到更大的新数组中,也就是说,第一次插入:会新建一个4元素长度数组,插入第五个元素时:新建一个8长度数组,并把旧数组中元素复制过来,旧数组则等待垃圾回收,以此类推。我们在不断插入元素时,会不断的进行重新分配空间,对元素进行复制的操作,如果我们一开始就知道该容器在业务中需要的大小,则可以在初始化时给一个具体的大小,也就是其中一个构造函数:

public ArrayList(int capacity)

另外,ArrayList还提供了Synchronized方法,返回值是一个ArrayList 但实际上在ArrayList类中有一个私有类SyncArrayList,它继承于ArrayList,在ArrayList方法重写增加了锁,以确保线程安全。

public static ArrayList Synchronized(ArrayList list)
{
    if (list == null)
    {
        throw new ArgumentNullException("list");
    }
    return new ArrayList.SyncArrayList(list);
}

  再来看List的代码:

private void EnsureCapacity(int min)
{
    if (this._items.Length < min)
    {
        int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
        if (num > 2146435071)
        {
            num = 2146435071;
        }
        if (num < min)
        {
            num = min;
        }
        this.Capacity = num;
    }
}

public void Add(T item)
{
    if (this._size == this._items.Length)
    {
        this.EnsureCapacity(this._size + 1);
    }
    T[] items = this._items;
    int size = this._size;
    this._size = size + 1;
    items[size] = item;
    this._version++;
}

和ArrayList的代码对比,基本完全相同,只是ArrayList维护着object数组,而List是泛型(模板)类,维护着泛型数组,List相比于ArrayList增加了类型安全以及ArrayList因object而引发的装拆箱性能问题。 因现有类型安全更快速的List,所以基本没有人在去用ArrayList了,而对元素的方便操作也让该容器成为最常用的容器之一。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: ArrayList C# List
最后更新:2021年4月18日

JomiXedYu

独游开发者 & 技术美术

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

JomiXedYu

独游开发者 & 技术美术

最新 热点 随机
最新 热点 随机
HLSL对Vulkan的适应性以及伪语义绑定 GPU呈现模式与垂直空白 自研引擎PulsarEngine的Shader编译流程 UE材质Custom节点与HLSL的HACK操作 UE5出现D3D12崩溃报错解决方案 游戏引擎脚本绑定的三种写法与利弊
HLSL对Vulkan的适应性以及伪语义绑定
UnityEditor开发之修改脚本Gizmos存放路径 xLua无法判断Unity对象为nil的问题 UE材质Custom节点与HLSL的HACK操作 HLSL对Vulkan的适应性以及伪语义绑定 Key社咖啡贴图psd WordPress域名更换使用MySQL替换文章链接
友情链接
  • DorinXL
  • 小博博客
  • 秋橘斋

COPYRIGHT © 2014-2023 雪千渔Blog. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

辽ICP备20006894号-1