Java学习手册:ArrayList&LinkedList&Vector

概述
名称特点
ArrayList不是线程安全的,默认每次扩充为原来的1.5倍(不可以设置)
Vector线程安全的,默认每次扩充为原来的2倍(每次扩充大小可以设置)
LinkedList不是线程安全的,(双向循环链表)顺序访问、增删效率高;双向链表;

一、ArrayList

ArrayList是一个数组队列,相当于动态数组(可变长数组)。与Java中的数组相比,它的容量能动态增长。

ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。

ArrayList 实现了RandomAccess接口,即提供了随机访问功能。RandomAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。

ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。

ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。

每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小。默认初始容量为10。随着ArrayList中元素的增加,它的容量也会不断的自动增长。(每次扩充空间的大小是不可以设置的) 在每次添加新的元素时,ArrayList都会检查是否需要进行扩容操作,扩容操作带来数据向新数组的重新拷贝,所以当我们知道具体业务数量的时候,在构造ArrayList时可以给ArrayList指定一个初始容量,这样就会减少扩容时数据的拷贝问题。当然在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这可以减少递增式再分类的数量。


二、Vector

Vector是Java中可以实现自动增长的对象数组,相比于ArrayList来说,Vector线程是安全的,也就是说是同步访问的。

java.util.vector提供了向量类(Vector)以实现类似动态数组的功能。

Vector 继承了AbstractList,实现了List;所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能。

Vector 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。

Vector 实现了Cloneable接口,即实现clone()函数,它能被克隆。

Vector 实现Serializable接口,支持序列化。

创建了一个向量类的对象后,可以往里随意插入不同类的对象,即不需顾及类型也不需预先选定向量的容量,并可以方便地进行查找。

Vector实际上是通过一个数组去保存数据的。当我们构造Vector时,若使用默认构造函数,则Vector的默认容量大小是10。随着Vector中元素的增加,当Vector容量不足以容纳全部元素时,Vector的容量会不断的自动增长。(每次扩充空间的大小是可以设置的)若容量增加系数 >0,则将容量的值增加“容量增加系数”;否则,将容量大小增加一倍。


三、LinkedList

ArrayList集合在查询元素时速度很快,但在增删元素时效率较低。为了克服这种局限性,可以使用List接口的另一个实现类LinkedList。该集合内部维护了一个双向循环链表,链表中的每一个元素都使用了引用的方式来记住它的前一个元素和后一个元素,从而可以将所有的元素彼此连接起来。当插入一个新元素时,只需要修改元素之间的这种引用关系即可,删除一个节点也是如此。

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。

LinkedList 实现 List 接口,能对它进行队列操作。

LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。

LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。

LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。

LinkedList 是非同步的。

LinkedList实际上是通过双向链表去实现的。既然是双向链表,那么它的顺序访问会非常高效,而随机访问效率比较低。LinkedList是双向链表的,但同时它也实现了List接口。也就是说,它实现了get(int location)、remove(int location)等根据索引值来获取、删除节点的函数。实际原理非常简单,它就是通过一个计数索引值来实现的。例如,当我们调用get(int location)时,首先会比较“location”和“双向链表长度的1/2”;若前者大,则从链表头开始往后查找,直到location位置;否则,从链表末尾开始先前查找,直到location位置


四、ArrayList、Vector和LinkedList三者的区别

ArrayList、Vector和LinkedList类均在java.util包中,均为可伸缩数组,即可以动态改变长度的数组。

ArrayList和Vector都是基于存储元素的Object[] array来实现的,它们会在内存中开辟一块连续的空间来存储,由于数据存储是连续的,因为,它们支持用序号(下标)来访问元素,同时索引数据的速度比较快。但在插入元素时需移动容器中的元素,所以对数据的插入操作执行的比较慢。ArrayList和Vector都有一个初始化的容量的大小,当里面的存储元素超过这个大小时就需要动态地扩充它们地存储空间。为了提高程序地效率,每次扩充容量,不是简单地扩充一个存储单元,二是一次增加多个存储单元。Vector默认扩充为原来的2倍(每次扩充空间的大小是可以设置的),而ArrayList默认扩充为原来的1.5倍(没有提供方法来设置空间扩充的方法)。

ArrayList和Vector的最大的区别就是synchronization(同步)的使用,没有一个ArrayList的方法是同步的,而Vector的绝大多数方法(例如add,insert,set,equals等)都是直接或间接同步的,所以Vector是线程安全的,ArrayList不是线程安全的。由于Vector提供了线程安全的机制,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起地不一致性,但实现同步需要很高地花费,因此,其性能要逊色于ArrayList。

LinkedList是采用双向列表来实现的,很适合数据地动态插入和删除,随机访问和遍历速度比较慢。对数据的索引需要从列表头开始遍历,因此用于随机访问则效率比较低,但是插入元素时不需要对数据进行移动,因此插入效率较高。同时LinkedList是非线程安全的容器。

在实际使用时,
当对数据的主要操作为索引或只在集合的末端增加删除元素时,使用ArrayList或Vector效率比较高
当对数据的操作主要为指定位置的插入或删除操作时,使用LinkedList效率比较高
当在多线程中使用容器时(即多个线程会同时访问该容器),选用Vector较为安全


五、习题

1、
题目:默认ArrayList的长度是10,ArrayList list = new ArrayList(20);中的list扩充几次?
答案:我们都知道,默认的ArrayList的长度是10个,所以如果要往list里添加20个元素肯定要扩充一次(扩充为原来的1.5倍),但是这里显示指明了需要多少空间,所以就一次性分配那么多空间,也就不需要扩充了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值