ArrayList 性能为什么差,来看看源码!

都说ArrayList的性能差,这是为什么呢?

我们知道Array是用数组的实现,初始化时要固定数组的大小。List是用链表实现,大小是可变的。

而ArrayList是用数组实现的可变大小。

源码:

using System;
namespace LinearList
{
    public class ArrayList
    {
        // 成员变量
        private const int _defaultCapacity = 4; //默认初始容量
        private object[] _items; //用于存放元素的数组
        private int _size; //指示当前元素个数
        //当元素个数为零时的数组状态
        private static readonly object[] emptyArray = new object[0];
        // 方法
        public ArrayList() //默认构造方法
        {   //这样做可以避免元素个数为零时的访问出错
            this._items = emptyArray;
        }
        //指定ArrayList初始容量的构造方法
        public ArrayList(int capacity)
        {
            if (capacity < 0)
            {   //当容量参数为负数时引发异常
                throw new ArgumentOutOfRangeException("capacity",
                    "为ArrayList指定的初始容量不能为负数");
            }
            //按照capacity参数指定的长度的值初始化数组
            this._items = new object[capacity]; 
        }
        //添加一个方法
        public virtual int Add(object value)
        {   //当空间满时
            if (this._size == this._items.Length)
            {   //调整空间
                this.EnsureCapacity(this._size + 1);
            }
            this._items[this._size] = value; //添加元素
            return this._size++; //使长度加1
        }
        //动态调整数组空间
        private void EnsureCapacity(int min)
        {
            if (this._items.Length < min)
            {   //空间加倍
                int num = (this._items.Length == 0) ?
                    _defaultCapacity : (this._items.Length * 2);
                if (num < min)
                {
                    num = min;
                }
                //调用Capacity的set访问器以按照num的值调整数组空间
                this.Capacity = num;
            }
        }
        //在指定索引入插入指定元素
        public virtual void Insert(int index, object value)
        {
            if ((index < 0) || (index > this._size))
            {
                throw new ArgumentOutOfRangeException("index", "索引超出范围");
            }
            if (this._size == this._items.Length)
            {   //当空间满时调整空间
                this.EnsureCapacity(this._size + 1);
            }
            if (index < this._size)
            {   //插入点后面的所有元素向后移动一位
                Array.Copy(this._items, index, 
                    this._items, index + 1, this._size - index);
            }
            this._items[index] = value; //插入元素
            this._size++; //使长度加1
        }
        //移除指定索引的元素
        public virtual void RemoveAt(int index)
        {
            if ((index < 0) || (index >= this._size))
            {
                throw new ArgumentOutOfRangeException("index", "索引超出范围");
            }
            this._size--; //使长度减1
            if (index < this._size)
            {   //使被删除元素后的所有元素向前移动一位
                Array.Copy(this._items, index + 1, 
                    this._items, index, this._size - index);
            }
            this._items[this._size] = null; //最后一位空出的元素置空
        }
        //裁减空间,使存储空间正好适合元素个数
        public virtual void TrimToSize()
        {
            this.Capacity = this._size;
        }

        // 属性
        public virtual int Capacity //指示ArrayList的存储空间
        {
            get
            {
                return this._items.Length;
            }
            set
            {
                if (value != this._items.Length)
                {
                    if (value < this._size)
                    {
                        throw new ArgumentOutOfRangeException("value", "容量太小");
                    }
                    if (value > 0)
                    {   //开辟一块新的内存空间存储元素
                        object[] destinationArray = new object[value];
                        if (this._size > 0)
                        {   //把元素搬迁到新空间内
                            Array.Copy(this._items, 0,
                                destinationArray, 0, this._size);
                        }
                        this._items = destinationArray;
                    }
                    else //最小空间为_defaultCapacity所指定的数目,这里是4
                    {
                        this._items = new object[_defaultCapacity];
                    }
                }
            }
        }
        public virtual int Count //只读属性,指示当前元素个数
        {
            get
            {
                return this._size;
            }
        }
        public virtual object this[int index] //索引器
        {
            get //获取指定索引的元素值
            {
                if ((index < 0) || (index >= this._size))
                {
                    throw new ArgumentOutOfRangeException("index", "索引超出范围");
                }
                return this._items[index];
            }
            set //设置指定索引的元素值
            {
                if ((index < 0) || (index >= this._size))
                {
                    throw new ArgumentOutOfRangeException("index", "索引超出范围");
                }
                this._items[index] = value;
            }
        }
    }
}

通过源码我们知道ArrayList初始化有两种方式,无参构造出一个长度为0的数组,有参构造指定长度的数组。

当Insert或Add时,如果发现长度不够,会用EnsureCapacity方法重新开辟空间,生成相应长度的数组,在把之前的数据copy过去。

当你一个一个数据add的时候,不知道要开辟多少回空间了,速度能快就怪了......

 

posted on 2015-02-05 10:44  荆小轲  阅读(278)  评论(0编辑  收藏  举报

导航