List接口
List是有序的 Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
和Set不同,List允许有相同的元素 。
除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素, 还能向前或向后遍历。
实现List接口的常用类有LinkedList,ArrayList, Vector和Stack。
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,因此必须捕获该异常。
Stack 类
Stack继承自 Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得 Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。
ArrayList, Vector和 LinkedList的比较
ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动等内存操作,所以 索引数据快 插入数据慢 ;Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差。
LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快 !
下面通过程序来验证一下:
import java.util.*;
public class TestList{
private List ll=new LinkedList();
private List al=new ArrayList();
private Vector v=new Vector();
private long start;
private long end;
private long time;
public TestList(){
for(int i=0;i<10000;i++)
ll.add(i);
for(int i=0;i<10000;i++)
al.add(i);
for(int i=0;i<10000;i++)
v.add(i);
}
public void testAddLinkedList(){
start=System.currentTimeMillis();
for(int i=0;i<1000;i++)
ll.add(5,5);
for(int i=0;i<1000;i++)
ll.remove(100);
end=System.currentTimeMillis();
time=end-start;
System.out.println("add time in LinkedList:"+time);
System.out.println();
}
public void testAddArrayList(){
start=System.currentTimeMillis();
for(int i=0;i<1000;i++)
al.add(5,5);
for(int i=0;i<1000;i++)
al.remove(100);
end=System.currentTimeMillis();
time=end-start;
System.out.println("add time in ArrayList:"+time);
System.out.println();
}
public void testAddVector(){
start=System.currentTimeMillis();
for(int i=0;i<1000;i++)
v.add(5,5);
for(int i=0;i<1000;i++)
v.remove(100);
end=System.currentTimeMillis();
time=end-start;
System.out.println("add time in Vector:"+time);
System.out.println();
}
public void testGetLinkedList(){
start=System.currentTimeMillis();
for(int i=0;i<2000;i++)
ll.get(i);
end=System.currentTimeMillis();
time=end-start;
System.out.println("get time in LinkedList:"+time);
System.out.println();
}
public void testGetArrayList(){
start=System.currentTimeMillis();
for(int i=0;i<2000;i++)
al.get(i);
end=System.currentTimeMillis();
time=end-start;
System.out.println("get time in ArrayList:"+time);
System.out.println();
}
public void testGetVector(){
start=System.currentTimeMillis();
for(int i=0;i<2000;i++)
v.get(i);
end=System.currentTimeMillis();
time=end-start;
System.out.println("get time in Vector:"+time);
System.out.println();
}
public static void main(String args[]){
TestList tl=new TestList();
tl.testAddLinkedList();
tl.testAddArrayList();
tl.testAddVector();
tl.testGetLinkedList();
tl.testGetArrayList();
tl.testGetVector();
}
}
运行结果
add time in LinkedList:0
add time in ArrayList:31
add time in Vector:63
get time in LinkedList:15
get time in ArrayList:0
get time in Vector:0