介绍
Vector是一个可动态扩展的线性表,底层实现是数组。 它的实现原理以及使用方式和ArrayList基本一致,不同点就是Vector是线程安全类,ArrayList非线程安全。
实现原理
增加元素:
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
在数组中,下标elementCount+1的位置添加一个元素,elementCount表示当前数组中实际存放元素的个数。
删除元素:
public synchronized void removeElementAt(int index) {
modCount++;
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
删除数组中指定index的位置的元素,操作步骤是将index+1到size-1之间的元素全部往前移动一位,即index+1到size-1的元素移动到下标为index到size-2的位置。
查询元素:
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
根据索引获取数组中的元素值。
修改元素:
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
根据index找到数组中已经存在的元素,然后将新的元素值赋值过去覆盖旧的值,同时将旧的值返回回去。
以上实现原理与ArrayList一致,具体详情请参考ArrayList部分,唯一的区别是在实现时通过synchronized对函数进行加锁来实现线程安全。
迭代器实现
迭代器遍历:
public void testVector(){
Vector<String> vector = new Vector<>();
vector.add("A");
vector.add("B");
vector.add("C");
vector.add("D");
vector.add("E");
removeElement(vector, "D");
}
public void removeElement(Vector vector, String element){
Iterator iterator = vector.iterator();
while (iterator.hasNext()){
String e = (String)iterator.next();
if (e.equals(element)){
iterator.remove();
break;
}
}
}
当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。 特别是对删除操作,由于数组删除一个元素后,数组长度会变,导致无法通过下标对数组进行完整的遍历。
迭代器的源码解析
迭代器的属性:
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
...
}
cursor游标,用来指向数组中下一个元素
lastRet指向遍历到的当前元素,初始值为-1
expectedModCount 表示数组修改的次数,它与modCount进行对比,如果修改次数不一致,就认为失败,用来定位快速失败。
Iterator.hasNext()实现
public boolean hasNext() {
// Racy but within spec, since modifications are checked
// within or after synchronization in next/previous
return cursor != elementCount;
}
cursor游标与elementCount数组元素个数相等,则表示已经遍历到了数组尾部
Iterator.next()实现
public E next() {
synchronized (Vector.this) {
checkForComodification();
int i = cursor;
if (i >= elementCount)
throw new NoSuchElementException();
cursor = i + 1;
return elementData(lastRet = i);
}
}
Iterator.remove()实现
public void remove() {
if (lastRet == -1)
throw new IllegalStateException();
synchronized (Vector.this) {
checkForComodification();
Vector.this.remove(lastRet);
expectedModCount = modCount;
}
cursor = lastRet;
lastRet = -1;
}
删除下标为lastRet对应的元素,把lastRet的值赋值给cursor,lastRet重置为-1。
Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,接下来通过一个图例来演示Iterator对象迭代元素的过程
Iterator没有使用前,lastRet指示器指向index为-1;cursor指向index为0的位置。
遍历步骤:
- 将cursor值保存到临时变量i中,cursor指向下一个元素,即cursor=cursor+1
- 将i的值赋给lastRet
图示如下:
执行: iterator.next()
执行: iterator.next()
执行: iterator.next()
执行: iterator.next()
最后遍历到数组尾部(cursor与elementCount相等), 通过iterator完成对vector的遍历。其他容器ArrayList,LinkedList的遍历也类似。