都说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的时候,不知道要开辟多少回空间了,速度能快就怪了......
时间: 2024-10-11 17:07:47