JAVA 集合类(java.util)源码阅读笔记------Vector

时间:2022-09-03 14:24:43

一、继承关系

public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
(1)继承自AbstractList类
(2)List接口:继承自Collection接口,同时自己也定义了一系列索引访问功能。
(3)RandomAccess:空接口,实现该接口代表该类拥有随机访问list对象的能力。
(4)Cloneable:空接口,实现该接口,重写Object的clone方法,否则会抛出异常。调用super.clone()实现对象的复制,如果对象中有引用,可以在super.clone后面进行处理。
(5)java.io.Serializable:空接口,实现该接口代表该类可序列化


二、成员变量

protected Object[] elementData;//内部还是采用一个数组保存list中的元素
protected int elementCount;//数组实际包含的元素的个数
protected int capacityIncrement;//每次增长的大小(不是增长率),当值小于等于0时,容量每次增长的容量为elementData.length(即倍增原数组的大小)
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //数组的最大容量

三、方法说明

(1)构造方法,如果不提供初始容量,则默认数组大小为10

public Vector() {
this(10);
}


(2)同步方法:trimToSize,将数组的容量修改成实际容量的大小,即令elementData.length=elementCount

    public synchronized void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (elementCount < oldCapacity) {
elementData = Arrays.copyOf(elementData, elementCount);
}
}


(3)同步方法:ensureCapacity,保证数组的最小容量

    public synchronized void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
modCount++;
ensureCapacityHelper(minCapacity);
}
}
//调用了ensureCapacityHelper:
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//调用了grow:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//如果capacityIncrement<0,则newCapacity=oldCapacity+oldCapacity;
//否则则newCapacity=oldCapacity+capacityIncrement;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
//如果增长后仍不能保证满足minCapacity,则令newCapacity = minCapacity
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//若增长后的大小大于允许的最大长度,则调用hugeCapacity
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//调用Arrays.copyof方法将elementData拷贝到一个容量为newCapacity的数组中。
//Arrays.copyOf(elementData, newCapacity)实际上是通过System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));来实现的
elementData = Arrays.copyOf(elementData, newCapacity);
}
//调用了hugeCapacity
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//MAX_ARRAY_SIZE=Integer.MAX_VALUE-8
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}


(4)同步方法:setSize,将elementData.length设置为newSize

    public synchronized void setSize(int newSize) {
modCount++;
if (newSize > elementCount) {
//若newSize<elementData.length,则不用扩容,否则需要扩容
ensureCapacityHelper(newSize);
} else {
//若newSize<elementData的实际大小(elementCount),则将newSize及其后面的数组都置为空
for (int i = newSize ; i < elementCount ; i++) {
elementData[i] = null;
}
}
elementCount = newSize;
}


(5)同步方法:capacity,返回数组的大小;size,返回数组包含的元素的个数;isEmpty,判断数组是否没有元素

    public synchronized int capacity() {
return elementData.length;
}
public synchronized int size() {
return elementCount;
}
public synchronized boolean isEmpty() {
return elementCount == 0;
}


(6)同步方法:删除index处的元素

    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) {
//将elementData从index+1到elementCount为止的元素向前移动一个位置,覆盖Index处的元素
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
//remove也是删除,但是没有判断index是否小于0
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);

int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--elementCount] = null; // Let gc do its work

return oldValue;
}


(7)同步方法:insertElementAt,在index处插入obj。

    public synchronized void insertElementAt(E obj, int index) {
modCount++;
if (index > elementCount) {
throw new ArrayIndexOutOfBoundsException(index
+ " > " + elementCount);
}
//先保证容量大于elementCount+1
ensureCapacityHelper(elementCount + 1);
//将elementData数组中index到elementCount之间的元素向后移动一位,给Index处空出位置
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
elementData[index] = obj;
elementCount++;
}


(8)同步方法:clone,重写Object父类中的方法

    public synchronized Object clone() {
try {
@SuppressWarnings("unchecked")
Vector<E> v = (Vector<E>) super.clone();
//复制一个Vector对象,然后给该对象中的elementData分配空间和填充元素
v.elementData = Arrays.copyOf(elementData, elementCount);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}


(9)同步方法:toArray

@SuppressWarnings("unchecked")
public synchronized <T> T[] toArray(T[] a) {
//如果参数a的size不够,则重新申请一个数组空间,并且复制elementData中内容
if (a.length < elementCount)
return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

System.arraycopy(elementData, 0, a, 0, elementCount);

if (a.length > elementCount)
a[elementCount] = null;

return a;
}



四、内部类

(1)Itr:单向迭代器,线程安全
    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;

public boolean hasNext() {
// Racy but within spec, since modifications are checked
// within or after synchronization in next/previous
return cursor != elementCount;
}

public E next() {
//加锁,本对象的对象锁
synchronized (Vector.this) {
checkForComodification();
int i = cursor;
if (i >= elementCount)
throw new NoSuchElementException();
cursor = i + 1;
return elementData(lastRet = i);
}
}

public void remove() {
if (lastRet == -1)
throw new IllegalStateException();
//加锁
synchronized (Vector.this) {
checkForComodification();
Vector.this.remove(lastRet);
expectedModCount = modCount;
}
cursor = lastRet;
lastRet = -1;
}

@Override
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
//加锁
synchronized (Vector.this) {
final int size = elementCount;
int i = cursor;
if (i >= size) {
return;
}
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) Vector.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
action.accept(elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}

final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}


(2)双向迭代器:ListItr,线程安全
    final class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}

public boolean hasPrevious() {
return cursor != 0;
}

public int nextIndex() {
return cursor;
}

public int previousIndex() {
return cursor - 1;
}

public E previous() {
//加锁
synchronized (Vector.this) {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
cursor = i;
return elementData(lastRet = i);
}
}

public void set(E e) {
if (lastRet == -1)
throw new IllegalStateException();
//加锁
synchronized (Vector.this) {
checkForComodification();
Vector.this.set(lastRet, e);
}
}

public void add(E e) {
int i = cursor;
//加锁
synchronized (Vector.this) {
checkForComodification();
Vector.this.add(i, e);
expectedModCount = modCount;
}
cursor = i + 1;
lastRet = -1;
}
}


(3)并行迭代器
static final class VectorSpliterator<E> implements Spliterator<E>

五、Iterator和Enumeration比较

在Java集合中,我们通常都通过 “Iterator(迭代器)” 或 “Enumeration(枚举类)” 去遍历集合。今天,我们就一起学习一下它们之间到底有什么区别。
我们先看看 Enumeration.java 和 Iterator.java的源码,再说它们的区别。
Enumeration是一个接口,它的源码如下:
package java.util;

public interface Enumeration<E> {

boolean hasMoreElements();

E nextElement();
}
Iterator也是一个接口,它的源码如下:
package java.util;

public interface Iterator<E> {
boolean hasNext();

E next();

void remove();
}
看完代码了,我们再来说说它们之间的区别。
(01) 函数接口不同
        Enumeration只有2个函数接口。通过Enumeration,我们只能读取集合的数据,而不能对数据进行修改。
        Iterator只有3个函数接口。Iterator除了能读取集合的数据之外,也能数据进行删除操作。
(02) Iterator支持fail-fast机制,而Enumeration不支持。
        Enumeration 是JDK 1.0添加的接口。使用到它的函数包括Vector、Hashtable等类,这些类都是JDK 1.0中加入的,Enumeration存在的目的就是为它们提供遍历接口。Enumeration本身并没有支持同步,而在Vector、Hashtable实现Enumeration时,添加了同步。
        而Iterator 是JDK 1.2才添加的接口,它也是为了HashMap、ArrayList等集合提供遍历接口。Iterator是支持fail-fast机制的:当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。
Enumeration速度比Iterator快。