ArrayList、LinkedList、Vector区别
来源:互联网 发布:抢报名的软件 编辑:程序博客网 时间:2024/05/19 12:25
一、
这三者都实现了List 接口.所有使用方式也很相似,主要区别在于因为实现方式的不同,所以对不同的操作具有不同的效率。
ArrayList 是一个可改变大小的数组.当更多的元素加入到ArrayList中时,其大小将会动态地增长.内部的元素可以直接通过get与set方法进行访问,因为ArrayList本质上就是一个数组.
LinkedList 是一个双链表,在添加和删除元素时具有比ArrayList更好的性能.但在get与set方面弱于ArrayList.
当然,这些对比都是指数据量很大或者操作很频繁的情况下的对比,如果数据和运算量很小,那么对比将失去意义.
Vector 和ArrayList类似,但属于强同步类。如果你的程序本身是线程安全的(thread-safe,没有在多个线程之间共享同一个集合/对象),那么使用ArrayList是更好的选择。
Vector和ArrayList在更多元素添加进来时会请求更大的空间。Vector每次请求其大小的双倍空间,而ArrayList每次对size增长50%.
而 LinkedList 还实现了 Queue 接口,该接口比List提供了更多的方法,包括 offer(),peek(),poll()等.
注意: 默认情况下ArrayList的初始容量非常小,所以如果可以预估数据量的话,分配一个较大的初始值属于最佳实践,这样可以减少调整大小的开销。
3. ArrayList示例
public
static
void
testArrayList() {
ArrayList<integer> al =
new
ArrayList<integer>();
al.add(
3
);
al.add(
2
);
al.add(
1
);
al.add(
4
);
al.add(
5
);
al.add(
6
);
al.add(
6
);
Iterator<integer> iter1 = al.iterator();
while
(iter1.hasNext()){
System.out.println(iter1.next());
}
}</integer></integer></integer>
public
static
void
testLinkedList() {
LinkedList<integer> ll =
new
LinkedList<integer>();
ll.add(
3
);
ll.add(
2
);
ll.add(
1
);
ll.add(
4
);
ll.add(
5
);
ll.add(
6
);
ll.add(
6
);
Iterator<integer> iter2 = ll.iterator();
while
(iter2.hasNext()){
System.out.println(iter2.next());
}
}</integer></integer></integer>
5. Vector
Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步类(synchronized).因此,开销就比ArrayList要大.正常情况下,大多数的Java程序员使用ArrayList而不是Vector,因为同步完全可以由程序员自己来控制。
6. ArrayList与LinkedList性能对比
时间复杂度对比如下:
* 表中的 add() 代表 add(E e),而 remove()代表 remove(int index)'
ArrayList 对于随机位置的add/remove,时间复杂度为 O(n),但是对于列表末尾的添加/删除操作,时间复杂度是 O(1). LinkedList对于随机位置的add/remove,时间复杂度为 O(n),但是对于列表 末尾/开头 的添加/删除操作,时间复杂度是 O(1).
我使用下面的代码来测试他们的性能:
public
static
void
testPerformance() {
ArrayList<integer> arrayList =
new
ArrayList<integer>();
LinkedList<integer> linkedList =
new
LinkedList<integer>();
int
times =
10
*
1000
;
// times = 100 * 1000;
// times = 1000 * 1000;
System.out.println(Test times = + times);
System.out.println(-------------------------);
// ArrayList add
long
startTime = System.nanoTime();
for
(
int
i =
0
; i < times; i++) {
arrayList.add(i);
}
long
endTime = System.nanoTime();
long
duration = endTime - startTime;
System.out.println(duration + <--ArrayList add);
// LinkedList add
startTime = System.nanoTime();
for
(
int
i =
0
; i < times; i++) {
linkedList.add(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println(duration + <--LinkedList add);
System.out.println(-------------------------);
// ArrayList get
startTime = System.nanoTime();
for
(
int
i =
0
; i < times; i++) {
arrayList.get(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println(duration + <--ArrayList get);
// LinkedList get
startTime = System.nanoTime();
for
(
int
i =
0
; i < times; i++) {
linkedList.get(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println(duration + <--LinkedList get);
System.out.println(-------------------------);
// ArrayList remove
startTime = System.nanoTime();
for
(
int
i = times -
1
; i >=
0
; i--) {
arrayList.remove(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println(duration + <--ArrayList remove);
// LinkedList remove
startTime = System.nanoTime();
for
(
int
i = times -
1
; i >=
0
; i--) {
linkedList.remove(i);
}
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println(duration + <--LinkedList remove);
}</integer></integer></integer></integer>
Test times =
10000
-------------------------
1469985
<--ArrayList add
3530491
<--LinkedList add
-------------------------
593678
<--ArrayList get
86914251
<--LinkedList get
-------------------------
625651
<--ArrayList remove
2164320
<--LinkedList remove
Test times =
100000
-------------------------
11480805
<--ArrayList add
26384338
<--LinkedList add
-------------------------
714072
<--ArrayList get
10040809061
<--LinkedList get
-------------------------
1203935
<--ArrayList remove
1595905
<--LinkedList remove
在
1000
*
1000
次的运行中,很长时间过后, LinkedList的get日志还没有打印出来,大概是
15
分钟左右,结果还是没有出来.
Test times =
1000000
-------------------------
132632998
<--ArrayList add
322885939
<--LinkedList add
-------------------------
3690752
<--ArrayList get
1520315361147
<--LinkedList get
-------------------------
8750043
<--ArrayList remove
13872885
<--LinkedList remove
他们性能的差异相当明显,LinkedList在 add和remove 上更快,而在get上更慢(原文是这样的).
译者注: 译者的编译和执行环境是 MyEclipse的JDK6,不论怎么看,都是 ArrayList更胜一筹,所以,该怎么选择,请根据自己的实际情况来决定,最好自己做测试,因为数据类型不同,JDK版本不同,优化不同,就可能有不同的结果。
根据时间复杂度表格,以及测试结果,我们可以判断何时该用ArrayList,何时该用LinkedList.
简单来说,LinkedList更适用于:
没有大规模的随机读取大量的增加/删除操作
二、演示各种List的使用
package com.sky.arrayset;
//ArrayList、Vector和LinkedList
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Stack;
import java.util.Vector;
/**
* 演示各种List的使用
* @author sky
*List能维护元素的次序,它允许元素重复
*/
public abstract class TestList {
/**初始化一个List*/
public static void init(List list){
if(list!=null){
list.add("aaa");
list.add("ccc");
list.add("bbb");
list.add("eee");
list.add("ddd");
}
}
/**输出List的内容*/
public static void output(List list){
if(list!=null){
//根据列表下标遍历,使用list.size()获取列表中元素的个数
for(int i=0;i<list.size();i++){
System.out.println("\n\t遍历list:"+list.get(i));
}
//或者用迭代器遍历
Iterator it=list.iterator();
Object value=null;
while(it.hasNext()){
value=it.next();
}
}
System.out.println();
}
/**使用ArrayList*/
public static void testArrayList(){
List list=new ArrayList();
init(list);
System.out.println("\n\t使用ArrayList:");
output(list);
}
/**使用Vector*/
public static void testVector(){
List list=new Vector();
init(list);
System.out.println("\n\t使用Vector:");
output(list);
}
/**使用LinkedList*/
public static void testLinkedList(){
List list=new LinkedList();
init(list);
System.out.println("\n\t使用LinkedList");
output(list);
}
public static void main(String[] args){
TestList.testArrayList();
TestList.testVector();
TestList.testLinkedList();
List list=new ArrayList();
init(list);
//List支持元素重复
list.add("aaa");
list.add("bbb");
System.out.println("\n\t插入原aaa,bbb后:");
output(list);
//指定元素出入的位置
list.add(1, "fff");
System.out.println("在下标为1处插入fff后:");
output(list);
List list2=new ArrayList();
list2.add("ggg");
list2.add("hhh");
//将另一个列表中的元素插入到列表中
list.addAll(list2);
System.out.println("添加list2大元素后:");
output(list);
//判断列表是否包含某一元素
//通过元素的equals方法,判断元素是否相等
System.out.println("\n\t list包含aaa?"+list.contains("aaa"));
//判断列表中是否包含了另一个列表中的所有元素
System.out.println("\n\t list包含list2中的所有元素?"+list.containsAll(list2));
//定位一个元素在列表中最先出现的位置
System.out.println("\n\t aaa在list中第一次出现的位置:"+list.indexOf("aaa"));
//定位一个元素在列表中最后出现的位置
System.out.println("\n\t aaa在list中最后一次出现的位置:"+list.lastIndexOf("aaa"));
//更新列表中某个位置的元素值
list.set(2, "xxx");
System.out.println("\n\t更新位置为2的元素为xxx后:");
output(list);
//删除列表中的某个元素,只删除第一次出现的出现的那个
list.remove("aaa");
System.out.println("\n\t删除元素aaa后");
output(list);
//删除列表中指定的位置的元素
list.remove(1);
System.out.println("\n\t删除下标为1的元素后");
output(list);
//删除列表中其他元素,只保留另一个列表中包含的元素
list.retainAll(list2);
System.out.println("\n\t删除list2包含以外的元素后");
output(list);
//删除列表中在另一个列表中也包含了的元素
list.removeAll(list2);
System.out.println("\n\t删除list2包含的元素后:");
output(list);
list.clear();//清空列表
//判断列表是否有数据
System.out.println("\n\t清空List后,list为空吗?"+list.isEmpty());
init(list);
//用列表中的某些元素构造一个新的列表
list2=list.subList(1, 3);
System.out.println("\n\t用list的第1个到第3个元素构造一个新的List:");
output(list2);
//用List特有的遍历器ListIterator遍历列表
//与普通的Iterator不用,它允许从两个方向遍历列表
ListIterator listIt=list.listIterator();
System.out.println("\n\t正向遍历列表");
while(listIt.hasNext()){
System.out.println("\n\t正向遍历列表 :"+listIt.next());
}
System.out.println("\n\t");
System.out.println("\n\t反向遍历列表");
while(listIt.hasPrevious()){
System.out.println("\n\t反向遍历列表:"+listIt.previous());
}
System.out.println();
//也可以使用ListIterator从list中间插入和删除元素
//只能在遍历当前位置进行添加和删除
listIt.add("newadd");
System.out.println("\n\t用ListIterator往列表中添加的元素newadd后:");
output(list);
listIt.next();
listIt.remove();
System.out.println("\n\t用ListIterator删除列表中元素后:");
output(list);
LinkedList linklist=new LinkedList();
init(linklist);
//添加元素到列表表头
linklist.addFirst("fff");
System.out.println("把fff放到列表表头后:");
output(linklist);
//添加元素到表尾
linklist.addLast("eee");
System.out.println("把eee放到列表尾后:");
output(linklist);
System.out.println("\n\t列表头元素:"+linklist.getFirst());
System.out.println("\n\t列表尾元素:"+linklist.getLast());
linklist.removeFirst();//删除列表表头的元素
System.out.println("删除列表头元素后:");
output(linklist);
linklist.removeLast();//删除列表尾的元素
System.out.println("删除列表的尾元素后:");
output(linklist);
Stack myStack=new Stack();
//插入元素,是插入到尾部
myStack.push("aaa");
myStack.push("bbb");
myStack.push("ccc");
myStack.push("ddd");
myStack.push("aaa");
myStack.push("ddd");
System.out.println("\n\t堆栈中的元素师:");
output(myStack);
System.out.println("\n\t堆栈尾部的元素:"+myStack.peek());
System.out.println("\n\t堆栈头部的元素:"+myStack.pop());
}
}
线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在java.util包中。
Collection是最基本的集合接口,一个Collection代表一组Object(即Collection的元素Elements)。JDK不提供直接继承自Collection的类,JDK提供的类都是继承自Collection的“子接口”如List,Set。
关系图如下:
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
从关系图上看出,Collection接口派生的两个接口是List和Set。(Map没有继承Collection接口)
对List的实现有3个,分别是Vector LinkedList ArrayList
LinkedList类
LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
List list = Collections.synchronizedList(new LinkedList(...));
ArrayList类
ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并 没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
和LinkedList一样,ArrayList也是非同步的(unsynchronized)。
Vector类
Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的 Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例 如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该 异常。
分析完后基本可以看出区别
Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间
(1)ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能含有“空隙”。
当数组大小不满足时会增加存储能力,将已有数组数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行拷贝,移动,代价比较高。因此,它适合随即查找和遍历,不适合插入合删除。
(2)Vector与ArrayList一样,也是通过数组实现的。不同的是它支持线程的同步,
即一时刻只有一个线程能够写Vector,避免多线程同时写引起的不一致性。但实现同步需要很高的花费,
因此,访问它比访问ArrayList慢。
(3)LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随即访问和遍历速度比较慢。另外,它还提供了List没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。
(4)因为ArrayList和Vector都是用数组实现的,所以,在添加和插入时,最好从表尾操作,而不要从中间或者表头开始,以避免数组移动引起的开销!
(5)可以为每个List生成ListIterator,支持双向遍历List,而且能够在ListIterator位置插入和删除元素。
(6)堆栈类继承Vector,它总是对列表的尾部数据进行操作,采用了先进后出的策略,自定义了插入、查看和弹出元素三个方法。
- ArrayList Vector LinkedList 区别
- Vector Arraylist LinkedList 区别
- ArrayList、Vector、LinkedList区别
- ArrayList,Vector,LinkedList区别
- Vector,ArrayList,LinkedList区别
- ArrayList、LinkedList、Vector区别
- Vector,ArrayList,LinkedList区别
- ArrayList、Vector、LinkedList区别
- ArrayList、LinkedList、Vector区别
- ArrayList LinkedList Vector 区别
- ArrayList LinkedList Vector 区别
- ArrayList、LinkedList、Vector区别
- ArrayList、LinkedList、Vector区别
- 区别 ArrayList LinkedList Vector
- vector和arrayList,LinkedList区别
- ArrayList,LinkedList,Vector的区别
- Java Vector ArrayList LinkedList 区别
- vector和arrayList,LinkedList区别
- csdn 英雄会第四届在线编程大赛·线上初赛:带通配符的数
- C++中的排序和踢重
- Android open project 收藏
- “呵呵,的确
- HTTP长连接(Comet)实现方式示例
- ArrayList、LinkedList、Vector区别
- 字符串单词拆分 Word Break
- Java BIO、NIO、AIO 学习
- C++中extern “C”含义深层探索
- NPOI方式 导出Excel表头
- “雷神之怒!”
- 高德地图警告解决
- Google的 FindBugs 实践
- PHP $_SERVER 变量