ArrayList 和 Vector 的区别
一.问题本质
Java集合的理解
二.问题解释
首先,我们来看看集合的类图。
其中vector这个集合类现在已经很少用了,但是面试题中还可能遇到。我们的学习重点,应该几种在ArrayList,linkedlist,hashset和treeset上。
接下来我们详细介绍一下ArrayList和vector,以后有机会再详细介绍其他接口。
我么能看到,这俩接口都是继承自list的。所以我们可以对比着学。
二者的实现大致相同,只是vector在ArrayList的基础上添加了线程安全关键字来约束。当执行synchronized修饰的方法前,系统会对该方法加一把锁,方法执行完成后释放锁。所以ArrayList的效率比较高,vector的安全性比较高。
1.
我们先来看看它的源码:
首先,它是基于数组实现的(elementData),并且实现了list接口。
例如,下面的add和remove方法,我们可以使用他们来和vector来进行对比。
public class ArrayList
transient Object[] elementData;
private int size;
}
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length) {
elementData =
this.grow();
}
elementData[s] = e;
this.size = s + 1;
}
public boolean add(E e) {
++
this.modCount;
this.add(e, this.elementData, this.size);
return true;
}
public E remove(int index) {
Objects.checkIndex(index,
this.size);
Object[] es =
this.elementData;
E oldValue = es[index];
this.fastRemove(es, index);
return oldValue;
}
2. Vector
我们首先看一下它的源码:
首先,它是基于数组实现的(elementData),并且实现了list接口,而且使用synchronized进行线程安全保证,这个可以在所有重要的方法中得到体现。
例如,下面的add和remove方法,可以看到,对外的接口使用synchronized进行修饰,保证线程安全。
public class Vector
protected Object[] elementData;
protected int elementCount;
}
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length) {
elementData =
this.grow();
}
elementData[s] = e;
this.elementCount = s + 1;
}
public synchronized boolean add(E e) {
++
this.modCount;
this.add(e, this.elementData, this.elementCount);
return true;
}
public synchronized E remove(int index) {
++
this.modCount;
if (index >= this.elementCount) {
throw new ArrayIndexOutOfBoundsException(index);
}
else {
E oldValue =
this.elementData(index);
int numMoved = this.elementCount - index - 1;
if (numMoved > 0) {
System.arraycopy(
this.elementData, index + 1, this.elementData, index, numMoved);
}
this.elementData[--this.elementCount] = null;
return oldValue;
}
}
三.区别
1. Vector是线程安全的,ArrayList是线程不安全的(多了个synchronized)
2. ArrayList在底层数组不够的时候,在原基础上扩充0.5倍,而vector扩充1倍。
四.延伸
1. 那么问题来了,为什么ArrayList线程不安全,怎么办?为什么大家不用vector呢?
原因大致有这么几个,因为线程安全,牺牲了效率;扩容的时候扩一倍,牺牲了空间;分配内存时容易失败;尾部增删,效率低。
2. 那么,如果用ArrayList又需要线程安全怎么办?
我们可以加上Collections.synchronizedList,它会自动将我们的list方法进行改变,最后返回给我们一个加锁了List
staticList arrayListSafe2 = Collections.synchronizedList(newArrayList());
那么,既然有ArrayList的线程安全同步方法,又有什么理由去使用vector呢?
3. 其实和ArrayList以及Vector方法形式的类还有,hashmap ,hashtable 以及stringbuild,stringbuffer。后者都是前者的基础上增加了线程安全的实现。