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的时候,不知道要开辟多少回空间了,速度能快就怪了......

时间: 2024-10-11 17:07:47

ArrayList 性能为什么差,来看看源码!的相关文章

从源码看Java集合之ArrayList

Java集合之ArrayList - 吃透增删查改 从源码看初始化以及增删查改,学习ArrayList. 先来看下ArrayList定义的几个属性: private static final int DEFAULT_CAPACITY = 10; private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; tra

Android:手把手带你分析 Protocol Buffer使用 源码

前言 习惯用 Json.XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存储格式,性能比 Json.XML 真的强!太!多! 由于 Google出品,我相信Protocol Buffer已经具备足够的吸引力 今天,我将讲解Protocol Buffer使用的源码分析,并解决以下两个问题: a. Protocol Buffer序列化速度 & 反序列化速度为何如此快 b. Pr

转:【Java集合源码剖析】Vector源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/35793865   Vector简介 Vector也是基于数组实现的,是一个动态数组,其容量能自动增长. Vector是JDK1.0引入了,它的很多实现方法都加入了同步语句,因此是线程安全的(其实也只是相对安全,有些时候还是要加入同步语句来保证线程的安全),可以用于多线程环境. Vector没有丝线Serializable接口,因此它不支持序列化,实现了Cloneable接口,能被克隆,实

Java集合源码学习笔记(四)HashMap分析

ArrayList.LinkedList和HashMap的源码是一起看的,横向对比吧,感觉对这三种数据结构的理解加深了很多. >>数组.链表和哈希表结构 数据结构中有数组和链表来实现对数据的存储,这两者有不同的应用场景,数组的特点是:寻址容易,插入和删除困难:链表的特点是:寻址困难,插入和删除容易:哈希表的实现结合了这两点,哈希表的实现方式有多种,在HashMap中使用的是链地址法,也就是拉链法.看下面这张流传很广的图, 拉链法实际上是一种链表数组的结构,由数组加链表组成,在这个长度为16的数

java1.7集合源码阅读: Vector

Vector是List接口的另一实现,有非常长的历史了,从jdk1.0开始就有Vector了,先于ArrayList出现,与ArrayList的最大区别是:Vector 是线程安全的,简单浏览一下Vector: 类定义: 1 public class Vector<E> 2 extends AbstractList<E> 3 implements List<E>, RandomAccess, Cloneable, java.io.Serializable Vector支

jQuery-1.9.1源码分析系列完毕目录整理

jQuery 1.9.1源码分析已经完毕.目录如下 jQuery-1.9.1源码分析系列(一)整体架构 jQuery-1.9.1源码分析系列(一)整体架构续 jQuery-1.9.1源码分析系列(二)jQuery选择器 jQuery-1.9.1源码分析系列(二)jQuery选择器续1 jQuery-1.9.1源码分析系列(二)jQuery选择器续2——筛选 jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——词法解析 jQuery-1.9.1源码分析系列(三) Sizzle选择

10个web前端jQuery开发者必备的源码组件

1.Conditioniz – 探测浏览器并条件加载 JavaScript 和 CSS Conditioniz 是一个快速.轻量级(3KB)的 JavaScript 工具,用于探测浏览器和分辨率并条件加载 JavaScript 和 CSS 文件.Conditioniz 从它的 jQuery 前身重建,现在速度要快50%.结合类名添加和 Conditionizr 集成的脚本和样式加载功能,允许你为不同的浏览器指定想加载的脚本和样式.浏览器嗅探通常被认为是不可靠的,Conditionizr 的建立就

【Java集合源码剖析】Vector源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/35793865 Vector简介 Vector也是基于数组实现的,是一个动态数组,其容量能自动增长. LinkedList是JDK1.0引入了,它的很多实现方法都加入了同步语句,因此是线程安全的(其实也只是相对安全,有些时候还是要加入同步语句来保证线程的安全),可以用于多线程环境. LinkedList没有丝线Serializable接口,因此它不支持序列化,实现了Cloneable接口,

JAVA 笔记(三) 从源码深入浅出集合框架

集合框架概述 以Java来说,我们日常所做的编写代码的工作,其实基本上往往就是在和对象打交道. 但显然有一个情况是,一个应用程序里往往不会仅仅只包含数量固定且生命周期都是已知的对象. 所以,就需要通过一些方式来对对象进行持有,那么通常是通过怎么样的方式来持有对象呢? 通过数组是最简单的一种方式,但其缺陷在于:数组的尺寸是固定的,即数组在初始化时就必须被定义长度,且无法改变. 也就说,通过数组来持有对象虽然能解决对象生命周期的问题,但仍然没有解决对象数量未知的问题. 这也是集合框架出现的核心原因,