【Java源码解读】Vector

源码来源:OpenJDK 10

简述

Vector实现了List接口;大小可变

ArrayList是线程不安全的,Vector的方法线程安全。Vector的public方法多用synchronized修饰,无此修饰的方法的内部实现也使用了synchronized。除此之外,与ArrayList原理相同,实现大同小异。如果没有线程安全的需求,还是推荐使用ArrayList,以避免不必要的性能开销

关于线程安全/同步

  • iterator和listIterator方法返回的迭代器都是fail-fast机制
  • elements方法返回的Enumeration<E>不是fail-fast机制的。也就是说,如果Enumeration被创建好后Vector实例的内部结构被更改,那么Enumeration的方法调用不会抛ConcurrentModificationException。但是这种改动的导致的结果影响是未定义的,所以也不推荐作出此类操作

构造方法

Vector(int initialCapacity, int capacityIncrement)

创建一个空的Vector,并指定内部数组的初始容量及容量增长的幅度(用于空间不足时决定扩容幅度)

Vector(int initialCapacity)

创建一个空的Vector,并指定内部数组的初始容量,且将容量增长幅度设置为0

就是Vector(initialCapacity, 0)

扫描二维码关注公众号,回复: 2593798 查看本文章

Vector()

创建一个空间的Vector,并指定内部数组的初始容量为10,容量增长幅度设置为0

就是Vector(10)

Vector(Collection<? extends E> c)

创建一个包含指定集合中所有元素的数组

具体实现就是,先将指定集合c中的元素(引用)复制到新数组中,并将新数组指定为Vector的内部数组,再设置字段elementCount以记录元素个数

其它方法

copyInto(Object[] anArray)

将所有元素(引用)拷贝到指定数组中

如果目标数组容量不足,会抛异常IndexOutOfBoundsException

如果有元素的类型与目标数组指定的类型不相符,会抛异常ArrayStoreException

trimToSize()

将内部数组的容量调整为当前元素的数量

可用此方法降低内存占用。modCount加1。(与ArrayList类似)

ensureCapacity(int minCapacity)

确保内部数组可容纳指定数量的元素

扩容操作与ArrayList类似。关键差异:

ArrayList(增加50%):

int newCapacity = oldCapacity + (oldCapacity >> 1);

Vector(增加capacityIncrement或翻倍):

int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
public synchronized void ensureCapacity(int minCapacity) {
    if (minCapacity > 0) {
        modCount++;
        if (minCapacity > elementData.length)
            grow(minCapacity);
    }
}

private Object[] grow(int minCapacity) {
    return elementData = Arrays.copyOf(elementData,newCapacity(minCapacity));
}

private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
    if (newCapacity - minCapacity <= 0) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return minCapacity;
    }
    return (newCapacity - MAX_ARRAY_SIZE <= 0)
        ? newCapacity
        : hugeCapacity(minCapacity);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

setSize(int newSize)

设置Vector实例的大小

modCount加1

如果newSize大于内部数组容量,则扩容

否则,如果newSize小于当前元素个数,则将多余的元素都置为null

最后elementCount被置为newSize

所以该操作可能会产生一些值为null的新元素

capacity()

返回内部数组的容量

size()

返回有效元素的个数

isEmpty()

判断vector是否为空

elements()

返回一个Enumeration<E>

虽然该方法不是同步的,但它所返回对象的nextElement()内部实现是同步的,同步对象就是该vector实例

contains(Object o)

判断是否存在于指定对象相等的元素

具体实现就是判断indexOf(Object o, 0)的返回值是否大于等于0。(与ArrayList类似)

indexOf(Object o)

获取首个与指定对象相等的元素的索引。如果没有匹配的元素,则返回-1

具体实现就是调用indexOf(Object o, 0)

indexOf(Object o, int index)

获取从指定索引开始,首个与指定对象相等的元素的索引

lastIndexOf(Object o)

获取最后一个与指定对象相等的元素的索引

与indexOf(Object o)类似,只是遍历方向相反

lastIndexOf(Object o, int index)

获取从指定索引开始(往前),首个与指定对象相等的元素的索引

与indexOf(Object o, int index)类似,只是遍历方向相反

elementAt(int index)

获取指定索引处的元素

firstElement()

获取首个元素

lastElement()

获取最后一个元素

setElementAt(E obj, int index)

将指定索引处的元素设置为指定对象

removeElementAt(int index)

移除指定索引处的元素

后继元素都会被向前移一格,原最后元素所在索引位置会置为null以利于GC。modCount加1,elementCount减1

remove(int index)

移除指定索引处的元素,并返回该元素

具体实现与removeElementAt(int index)类似

removeElement(Object obj)

移除第一个与指定对象相等的元素,并返回true(成功移除)或false(不存在与指定对象相等的元素)

具体实现是,先调用indexOf(Object o)找到目标索引,再调用removeElementAt(int index)移除目标元素

modCount加2,因为刚进入该方法就加1,removeElementAt(int index)内部又加1。elementCount减1

removeAllElements()

移除所有元素

所有元素置为null,modCount加1,elementCount置为0

insertElementAt(E obj, int index)

将指定元素插入到指定索引处

原索引处元素及其它后续元素将被向后移一格。modCount加,elementCount加1

addElement(E obj)

将指定元素添加到vector末尾

modCount加1,elementCount加1

clone()

创建一个浅拷贝的副本

toArray()

创建并返回一个包含各元素的数组

toArray(T[] a)

与toArray()类似,该方法时泛型形式

对指定数组a的处理方式与ArrayList.toArray(T[] a)相同

get(int index)

获取指定索引处的元素

set(int index, E element)

将指定索引处的元素替换为指定的对象,并返回原元素

add(E e)

将指定对象添加到末尾,并返回true

modCount加1,elementCount加1

remove(Object o)

移除首个与指定对象相等的元素

具体实现就是调用removeElement(Object o)

add(int index, E element)

将指定对象插入到指定索引处

具体实现就是调用insertElementAt(E obj, int index)

remove(int index)

移除指定索引处的元素,并返回该元素

后继元素都会被往前移一格;modCount加;elementCount减1

clear()

移除所有元素

具体实现就是调用removeAllElements()

containsAll(Collection<?> c)

判断指定集合c中的元素是否在vector都有相等的元素

该方法就是对父类方法AbstractCollection.containsAll(Collection<?> c)的同步化封装

addAll(Collection<? extends E> c)

将指定集合c中的元素都添加到末尾,并返回true(有新元素添加)或false(集合c为空)

modCount加1;elementCount增加的值就是新元素个数

removeAll(Collection<?> c)

移除vector中所有已存在于指定集合c的元素,并返回true(有元素被移除)或false(没有元素被移除)

具体实现与ArrayList.removeIf(Predicate<? super E> filter)类似

retainAll(Collection<?> c)

移除vector中所有指定集合c不包含的元素,并返回true(有元素被移除)或false(没有元素被移除)

具体实现与removeAll(Collection<?> c)类似,只是判断元素是否需移除的条件取反

removeIf(Predicate<? super E> filter)

移除所有符合指定筛选器的元素

具体实现与removeAll(Collection<?> c)类似,调用的是相同的子方法

addAll(int index, Collection<? extends E> c)

将指定集合中的所有元素插入到指定索引处,并返回true(有新元素加入)或false(没有新元素加入)

modCount加1,elementCount增加的值就是新增元素的个数

equals(Object o)

判断vector实例是否与指定的对象相等

相等的条件:

指定对象o是List
与vector实例的元素个数相同
每个对应位置上的元素都相等

该方法是对父类方法AbstractList.equals(Object o)的同步化封装

hashCode()

获取vector实例的哈希值

该方法是对父类方法AbstractList.hashCode()的同步化封装

toString()

获取vector实例的字符串表示形式(包含每个元素的字符串表示形式)

该方法是父类方法AbstractCollection.toString()的同步化封装

subList(int fromIndex, int toIndex)

获取指定索引区间的子List。包括fromIndex,不包括toIndex

该子list只是vector的一个视图,对子list的操作会调用原vector的方法,对vector产生影响

该方法是对父类方法AbstractList.subList(int index, int toIndex)的同步化封装,该方法用synchronized修饰,且用Collections.synchronizedList(List<T> list, Object mutex)对父类方法的返回值进行封装,其中mutex是该vector实例自身

listIterator(int index)

获取从指定索引处开始的ListIterator<E>

listIterator()

获取一个从0索引开始的ListIterator<E>。这是listIterator(int index)的一个特例

forEach(Consumer<? super E> action)

对每个元素应用指定的操作

replaceAll(UnaryOperator<E> operator)

将所有元素替换为将operator处理过后得到的结果。modCount会增加1

sort(Comparator<? super E> c)

使用指定的比较器,对所有元素进行排序,排序结果反映在原内部数组

spliterator()

返回一个Spliterator<E>(可分割迭代器,用于并行遍历)

其它

单纯从代码整洁性角度而言,Vector有较多值得优化的地方。这可能和Vector在现实中使用频率较低有关(虽未被标记为@Deprecated,但网上很早就有弃用该类的声音)

猜你喜欢

转载自pre.iteye.com/blog/2428189