1.简介(有参考)
vector是一个矢量队列,继承自AbstractList,实现了List,RandomAccess,Cloneable,java.io.Serializable等接口。
vector继承AbstractList,实现了List,所以,它是一个队列,实现了增加、删除、修改、遍历等功能。
vector实现了RandomAccess,可以进行随机访问。
vector实现了Cloneable,重载了其中的clone()方法,可以进行克隆。
vector实现了Serializable,可进行序列化。
vector是线程安全的(后面会讲到)
2.重要成员变量及构造函数
protected Object[] elementData; //数组缓冲区,存储矢量的组件即数据
protected int elementCount; //数组的大小
protected int capacityIncrement; //容量增长度,自动增长,如果增长度很慢趋近于零,则会成倍增长。
public Vector() { //默认大小为10
this(10);
}
public Vector(int initialCapacity) {
this(initialCapacity, 0); //默认容量增长度为0
}
public Vector(int initialCapacity, int capacityIncrement) {....} // 执行真正的初始化
public Vector(Collection<? extends E> c) { //集合为参,初始化
elementData = c.toArray();
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
//Arrays的toArray()方法不一定会返回Object[].class;
/** 与传进来的collection有关,如:
* List<Object> aa = Arrays.asList("a",1,'c',0.2f);elementData.getClass() 为object[]
* List<String> dd = Arrays.asList("a","bb");elementData.getClass() 为string[]
* 因为定义的elementData 就是为object[],不然会报错
* */
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
3.常用方法
public synchronized boolean add(E e) {
modCount++; //修改次数自增
ensureCapacityHelper(elementCount + 1); //确保容量足够
elementData[elementCount++] = e; //新增的空位置添加新元素
return true;
}
private void ensureCapacityHelper(int minCapacity) {
if (minCapacity - elementData.length > 0)
grow(minCapacity); //执行扩容方法
}
private void grow(int minCapacity) {
//当前vector的长度
int oldCapacity = elementData.length;
//新的容量-当前的+(增长度设置了且大于零则直接使用,否则设置的增长度为当前长度,即每次扩大一倍)
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
//扩容一倍或扩容后(n倍)不够,以需要的容量为新的容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity); //底层还是System.arraycopy方法,将源数组扩展了一个空位置(add方法最后执行添加)
}
set\get 方法实现
E elementData(int index) {
return (E) elementData[index];
}
remove等方法与ArrayList差不多,不再赘述
遍历:
Iterator it = vector.iterator(); //迭代器遍历
while (it.hasNext()){
Object obj = it.next();
System.out.println(obj);
}
for (int i = 0; i < vector.size(); i++) { //随机访问
System.out.println(vector.get(i));
}
for (Object obj : vector) { //常见foreach
System.out.println(obj);
}
Object obj = null; //枚举遍历
Enumeration eums = vector.elements();
while (eums.hasMoreElements()){
obj = eums.nextElement();
System.out.println(obj);
}
--1.8新特性遍历集合lambda表达式
1.vector.forEach(value -> System.out.println(value));
2.vector.forEach(new Consumer<Object>() {
@Override
public void accept(Object value) {
if (vector.size() >0){
System.out.println(value);
}
}
});
3.vector.forEach(value -> {
if (vector.size() >0){
System.out.println(value);
}
});
--clone、remove、toarray等很多方法,底层都是关于数组的copy、增删相关操作。
4.扩容机制
private void grow(int minCapacity) {
//当前vector的长度
int oldCapacity = elementData.length;
//新的容量-当前的长度+(增长度设置了且大于零则直接使用即扩大capacityIncrement,否则设置的增长度为当前长度即每次扩大一倍)
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
//扩容一倍或扩容后(n倍)不够,以需要的容量为新的容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity); //底层还是System.arraycopy方法,将源数组扩展了一个空位置(add方法最后执行添加)
}
5.快速失败机制
同ArrayList的快速失败机制--如在迭代器里面做add、remove操作。 因为调用iterator的next()方法 会判断modCount(修改次数)。
6.线程安全方面
问:对于线程安全的集合类(例如Vector)的任何操作是不是都能保证线程安全?
答:同步容器中的所有自带方法都是线程安全的,因为方法都使用synchronized关键字标注。但是,对这些集合类的复合操作无法保证其线程安全性。需要客户端通过主动加锁来保证。
由于我们自己已知Vector等同步容器是线程安全的,所以我们通常在多线程场景中会直接拿来使用,并不会考虑太多,从而可能导致问题。
所以,我们在使用同步容器的时候,如果只使用其中的自带方法,那么可以放心使用,因为他们是线程安全的,但是如果我们想做复合操作,尤其是涉及到删除容器中的元素时,一定要注意是否需要客户端主动加锁。
下面,我们考虑以下代码,如果在多线程场景中使用会不会出现线程安全问题:(如一个线程先删除了大小为5的数组的最高位的数据,另一个再get最高位,则会报错)
for (int i = 0; i < v.size(); i++) {
System.out.println(v.get(i));
}
显然,以上代码在迭代的过程中,并不会出现线程安全问题。但是,如果在程序中还有以下代码有可能被同时调用呢?
for (int i = 0; i < v.size(); i++) {
v.remove(i);
}
由于,不同线程在同一时间操作同一个Vector,其中包括删除操作,那么就同样有可能发生线程安全问题。所以,在使用同步容器的时候,如果涉及到多个线程同时执行删除操作,就要考虑下是否需要加锁。
synchronized (vector) {for(...)} 加锁
参考链接:http://www.importnew.com/26359.html
7.总结
vector实际上和ArrayList的功能大体相似,但是它基本所有的方法都加了Synchronized关键字,即同步安全的。 但就是因为加了Synchronized,当达到一定数据量时,在性能方面是不如ArrayList的,而且需注意的就是--vector在多线程情况下,也并不安全。