`

【Java源码解读】Vector

    博客分类:
  • Java
 
阅读更多

源码来源: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)

 

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,但网上很早就有弃用该类的声音)

 

 

0
0
分享到:
评论

相关推荐

    Java中的ArrayList的底层源码解读、LinkedList、Vector的区别介绍

    阅读建议:结合代码进行阅读,在阅读的时候进行代码的比对,以及做笔记,结合自己不懂的地方反复观看,源码解读较为枯燥,文档中的步骤给的都很详细,需要大家结合源码一步一步的跟着步骤进行阅读,

    本仓库记录了我的Java学习进阶之路,涵盖了Java基础、JDK源码、JVM中的重要知识,附有代码和博客讲解,旨在提供一个Java在线共享学习平台,帮助更多的Java学习入门者进阶 .zip

    作者目录Java基础Java基础学习(1)——引用Java基础学习(2)——注解Java基础...VectorJava集合框架源码解读(2)——HashMapJava集合框架源码解读(3)——LinkedHashMapJava集合框架源码解读(4)——WeakHashMapJava集合框架...

    JAVA Vector源码解析和示例代码

    【JAVA Vector 源码解析和示例代码】 在Java编程语言中,`Vector`类是集合框架的一部分,早在JDK 1.0版本就已经存在。`Vector`类继承自`AbstractList`并实现了`List`, `RandomAccess`, `Cloneable`等接口,提供了...

    清华妹子的Java仓库(进阶学习路线)

    Java集合框架源码解读(1)——ArrayList、LinkedList和Vector Java集合框架源码解读(2)——HashMap Java集合框架源码解读(3)——LinkedHashMap Java集合框架源码解读(4)——WeakHashMap Java集合框架源码解读

    java8源码-JavaRobot:Java学习笔记,JavaLearningNote

    源码解读 String源码系列 List源码系列 ArrayList LinkedList CopyOnWriteArrayList Vector Map源码系列 HashMap LinkedHashMap ConcurrentHashMap TreeMap Hashtable Set源码系列 HashSet LinkedHashSet TreeSet ...

    java采购管理系统源码-clojure-notes:clojure源码解读

    在源码解读中,我们可以学习到如何使用Clojure的数据结构,如 Persistent Vector 和 Map,它们提供了高效且不可变的数据操作。此外,Clojure的函数式编程特性允许我们编写无副作用的代码,这对于处理复杂业务逻辑...

    java范例开发大全(pdf&源码)

    实例220 运用Vector 397 实例221 改变Properties文件中的键值 399 第13章 多线程编程(教学视频:121分钟) 405 13.1 多线程的五种基本状态 405 实例222 启动线程 405 实例223 参赛者的比赛生活(线程休眠唤醒) 407...

    java面试宝典

    我们可以得知这本《java面试宝典》旨在帮助求职者全面准备Java开发相关的技术面试,其中不仅包含了大量关于Java核心知识点的解析,还涉及了并发编程、JVM原理以及源码层面的深度理解,非常适合即将参加Java技术面试...

    MAC加密算法源码

    本篇文章将深入分析一个基于银联标准的MAC加密算法实现源码,并对其进行详细解读。 #### 二、源码解析 ##### 2.1 类结构简介 ```java public class MacEcbUtils { //... } ``` `MacEcbUtils`类是整个MAC加密...

    Java范例开发大全(全书源程序)

    实例220 运用Vector 397 实例221 改变Properties文件中的键值 399 第13章 多线程编程(教学视频:121分钟) 405 13.1 多线程的五种基本状态 405 实例222 启动线程 405 实例223 参赛者的比赛生活(线程休眠唤醒...

    svm_SVM_songg6y_源码.zip

    【源码解读】 由于没有具体的文件内容,我们可以假设这个压缩包包含以下常见组成部分: 1. **代码文件**:可能包含用各种编程语言(如Python、C++或Java)实现的SVM算法。这些文件可能包括训练模型、预测新数据、...

    java基于蚁群算法路由选择可视化动态模拟(论文+开题报告+翻译+任务书+外文翻译).zip

    此外,论文还对比了蚁群算法与其他路由选择策略,如最短路径优先(Shortest Path First, SPF)和距离向量路由(Distance Vector Routing, DVR),论证了蚁群算法在动态网络环境下的优越性能。 开题报告则介绍了研究...

    tarot:法国塔罗牌的Clojure实现

    2. ** immutable数据结构**:Clojure的数据结构如vector、list、map等都是不可变的,这确保了共享状态的安全性。 3. **闭包和高阶函数**:支持闭包和函数作为一等公民,可以作为参数传递和作为返回值。 4. **动态...

Global site tag (gtag.js) - Google Analytics