A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

对集合类理解的不透彻啊

评分

参与人数 1技术分 +1 收起 理由
黄晓鑫 + 1 很给力!

查看全部评分

2 个回复

倒序浏览
ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快.

   一、Java ArrayList详解

    1、什么是ArrayList

    ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处:

    动态的增加和减少元素 实现了ICollection和IList接口 灵活的设置数组的大小

    2、如何使用ArrayList

    最简单的例子:

    ArrayList List = new ArrayList();

    for( int i=0;i<10;i++ ) //给数组增加10个Int元素

    List.Add(i);

    //程序做一些处理

    List.RemoveAt(5);//将第6个元素移除

    for( int i=0;i<3;i++ ) //再增加3个元素

    List.Add(i+20);

    Int32[] values = (Int32[])List.ToArray(typeof(Int32));//返回ArrayList包含的数组

    这是一个简单的例子,虽然没有包含ArrayList所有的方法,但是可以反映出ArrayList最常用的用法

   
    如果使用ArrayList.Synchronized方法返回的实例,那么就不用考虑线程同步的问题,这个实例本身就是线程安全的,实际上ArrayList内部实现了一个保证线程同步的内部类,ArrayList.Synchronized返回的就是这个类的实例,它里面的每个属性都是用了lock关键字来保证线程同步.

    ****

    但是,使用这个方法(ArrayList.Synchronized)并不能保证枚举的同步,例如,一个线程正在删除或添加集合项,而另一个线程同时进行枚举,这时枚举将会抛出异常.所以,在枚举的时候,你必须明确使用 SyncRoot 锁定这个集合.

    Hashtable与ArrayList关于线程安全性的使用方法类似.

   
    3、ArrayList最佳使用建议

    这一节我们来讨论ArrayList与数组的差别,以及ArrayList的效率问题

    (1)ArrayList是Array的复杂版本

    ArrayList内部封装了一个Object类型的数组,从一般的意义来说,它和数组没有本质的差别,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法.

    (2)内部的Object类型的影响

    对于一般的引用类型来说,这部分的影响不是很大,但是对于值类型来说,往ArrayList里面添加和修改元素,都会引起装箱和拆箱的操作,频繁的操作可能会影响一部分效率.

    但是恰恰对于大多数人,多数的应用都是使用值类型的数组.

    消除这个影响是没有办法的,除非你不用它,否则就要承担一部分的效率损失,不过这部分的损失不会很大.

    (3)数组扩容

    这是对ArrayList效率影响比较大的一个因素.

    每当执行Add、AddRange、Insert、InsertRange等添加元素的方法,都会检查内部数组的容量是否不够了,如果是,它就会以当前容量的两倍来重新构建一个数组,将旧元素Copy到新数组中,然后丢弃旧数组,在这个临界点的扩容操作,应该来说是比较影响效率的.

    例1:比如,一个可能有200个元素的数据动态添加到一个以默认16个元素大小创建的ArrayList中,将会经过:

    16*2*2*2*2 = 256

    四次的扩容才会满足最终的要求,那么如果一开始就以:

    ArrayList List = new ArrayList( 210 );

    的方式创建ArrayList,不仅会减少4次数组创建和Copy的操作,还会减少内存使用.

    例2:预计有30个元素而创建了一个ArrayList:

    ArrayList List = new ArrayList(30);

    在执行过程中,加入了31个元素,那么数组会扩充到60个元素的大小,而这时候不会有新的元素再增加进来,而且有没有调用TrimSize方法,那么就有1次扩容的操作,并且浪费了29个元素大小的空间.如果这时候,用:

    ArrayList List = new ArrayList(40);

    那么一切都解决了.

    所以说,正确的预估可能的元素,并且在适当的时候调用TrimSize方法是提高ArrayList使用效率的重要途径.

    (4)频繁的调用IndexOf、Contains等方法(Sort、BinarySearch等方法经过优化,不在此列)引起的效率损失

    首先,我们要明确一点,ArrayList是动态数组,它不包括通过Key或者Value快速访问的算法,所以实际上调用IndexOf、Contains等方法是执行的简单的循环来查找元素,所以频繁的调用此类方法并不比你自己写循环并且稍作优化来的快,如果有这方面的要求,建议使用Hashtable或SortedList等键值对的集合.

    ArrayList al=new ArrayList();

    al.Add("How");

    al.Add("are");

    al.Add("you!");

    al.Add(100);

    al.Add(200);

    al.Add(300);

    al.Add(1.2);

    al.Add(22.8);

    ……

    //第一种遍历 ArrayList 对象的方法

    foreach(object o in al)

    {

    Console.Write(o.ToString()+" ");

    }

    //第二种遍历 ArrayList 对象的方法

    IEnumerator ie=al.GetEnumerator();

    while(ie.MoveNext())

    {

    Console.Write(ie.Curret.ToString()+" ");

    }

    //第三种遍历 ArrayList 对象的方法

    我忘记了,好象是 利用 ArrayList对象的一个属性,它返回一此对象中的元素个数.

    然后在利用索引

    for(int i=0;i<Count;i++)

    {

    Console.Write(al.ToString()+" ");

    }



   二、Java Vector详解

    Vector 类 提 供 了 实 现 可 增 长 数 组 的 功 能, 随 着 更 多 元 素 加 入 其 中, 数 组 变 的 更 大. 在 删 除 一 些 元 素 之 后, 数 组 变 小.

    Vector 有 三 个 构 造 函 数,

    public Vector(int initialCapacity,int capacityIncrement)

    public Vector(int initialCapacity)

    public Vector()

   
    三、Java LinkedList详解

    栈和队列是两种特殊的线性表,它们的逻辑结构和线性表相同,只是其运算规则较线性表有更多的限制,故又称它们为运算受限的线性表.

    LinkedList数据结构是一种双向的链式结构,每一个对象除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素,和数组的顺序存储结构(如:ArrayList)相比,插入和删除比较方便,但速度会慢一些.

    栈的定义

    栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表.

    (1)通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom).

    (2)当表中没有元素时称为空栈.

    (3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表.

    栈的修改是按后进先出的原则进行.每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除.

   
    队列定义

    队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表

    (1)允许删除的一端称为队头(Front).

    (2)允许插入的一端称为队尾(Rear).

    (3)当队列中没有元素时称为空队列.

    (4)队列亦称作先进先出(First In First Out)的线性表,简称为FIFO表.

   

评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

回复 使用道具 举报
你可以把ArrayList当作一个数组,你想想,你如果要在数组的某一个位置中添加一个元素或删除,是不是要把其它的元素依次往后移或前移,这样是不是增删效率很低,所以就有了LinkedList,你可以把它当作链表,但是它在查找的时候需要依次的便利每一个元素,直到找到为止,那么它也就查找效率低,这样就很好理解了,你要是频繁的增删那就用LinkedList, 要是频繁的查找就用ArrayList

评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马