概述

上文「JDK源码分析-ArrayList」主要分析了 ArrayList 的实现原理。本文分析 List 接口的另一个实现类:Vector。

Vector 的内部实现与 ArrayList 类似,也可以理解为一个「可变数组」。其继承结构如下(省略部分接口):

PS: 由于 Vector 目前使用较少,且官方也推荐在无线程安全的需求时使用 ArrayList 代替 Vector,这里仅研究其实现原理。

stackoverflow 也有相关的讨论:

https://stackoverflow.com/questions/1386275/why-is-java-vector-and-stack-class-considered-obsolete-or-deprecated

仍然从其构造器入手进行分析。

构造器

Vector 对外提供四个构造器(内部可以认为是两个),其一:

protected Object[] elementData;

protected int capacityIncrement;

// 无参构造器
public Vector() {
this(10);
} // 指定容量的构造器
public Vector(int initialCapacity) {
this(initialCapacity, 0);
} // 指定初始容量和容量增长因子的构造器
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}      

与 ArrayList 类似,Vector 内部也维护了一个 Object 类型的数组(elementData)来存储元素(默认初始容量也是 10)。不同的是:Vector 比 ArrayList 的构造器多了一个参数 capacityIncrement,该变量也导致了二者的扩容方式略有不同,后面进行分析。

其二:入参为集合的构造器

public Vector(Collection<? extends E> c) {
elementData = c.toArray();
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}

扩容原理分析

我们仍从其 add() 方法入手进行分析:

public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}

注意这里的关键字 synchronized。观察可以发现:Vector 内部许多方法都使用了该关键字,这也是 Vector 实现线程安全的方式,简单粗暴!

其扩容方法实现如下:

/**
* The number of valid components in this {@code Vector} object.
* Components elementData[0] through
* elementData[elementCount-1] are the actual items.
*/
protected int elementCount; /*
* 该方法是非同步的
* 因为 Vector 内部调用该方法的地方都使用了 synchronized 关键字进行同步,这里不再额外使用
*/
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
// 大于数组容量时再进行扩容操作
if (minCapacity - elementData.length > 0)
grow(minCapacity);
} private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
} private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}

从这里可以看出,Vector 与 ArrayList 的扩容方式基本一致,只是新容量的计算方式有所不同,这里分析下其新容量大小:

int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);

Vector 计算扩容后的新容量时,根据 capacityIncrement 的值可以分为两种情况:

1. capacityIncrement > 0:新容量 = 旧容量 + capacityIncrement;

2. capacityIncrement <= 0:新容量 = 旧容量 * 2。

线程安全性

Vector 是线程安全的,它实现线程安全的方式也很简单粗暴:直接在方法上使用 synchronized 关键字进行同步。

Vector 小结

1. 与 ArrayList 类似,Vector 也可以认为是「可变数组」;

2. 扩容原理与 ArrayList 基本一致,只是新容量计算方式略有不同:指定增长容量时,新容量为旧容量 + 增长容量;否则扩容为旧容量的 2 倍;

3. 线程安全的,实现方式简单(synchronized);

4. 当前使用较少,这里仅学习其实现原理。

Stay hungry, stay foolish.

PS: 本文首发于微信公众号。

【JDK】JDK源码分析-Vector的更多相关文章

  1. JDK Collection 源码分析(2)—— List

    JDK List源码分析 List接口定义了有序集合(序列).在Collection的基础上,增加了可以通过下标索引访问,以及线性查找等功能. 整体类结构 1.AbstractList   该类作为L ...

  2. JDK AtomicInteger 源码分析

    @(JDK)[AtomicInteger] JDK AtomicInteger 源码分析 Unsafe 实例化 Unsafe在创建实例的时候,不能仅仅通过new Unsafe()或者Unsafe.ge ...

  3. 设计模式(十八)——观察者模式(JDK Observable源码分析)

    1 天气预报项目需求,具体要求如下: 1) 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方). 2) 需要设计开放型 API,便于其他第三方也能接入气象 ...

  4. JDK Collection 源码分析(3)—— Queue

    @(JDK)[Queue] JDK Queue Queue:队列接口,对于数据的存取,提供了两种方式,一种失败会抛出异常,另一种则返回null或者false.   抛出异常的接口:add,remove ...

  5. JDK Collection 源码分析(1)—— Collection

    JDK Collection   JDK Collection作为一个最顶层的接口(root interface),JDK并不提供该接口的直接实现,而是通过更加具体的子接口(sub interface ...

  6. Caffe学习系列(17): caffe源码分析 vector<Blob<Dtype>*>& bottom(转)

    转自:http://blog.csdn.net/qq_14975217/article/details/51524042 Blob:4个维度 n x c x h x w: bottom[0] .bot ...

  7. caffe源码分析 vector<Blob<Dtype>*>& bottom

    Blob:4个维度 n x c x h x w: bottom[0] .bottom[1]代表该层有几个输入. bottom[0]->count(): 输入中,元素的总维数(个数) bottom ...

  8. STL源码分析-vector

    http://note.youdao.com/noteshare?id=55dc651a7489f1413b3a3169401dcf94

  9. Java集合之Vector源码分析

    概述 Vector与ArrayLIst类似, 内部同样维护一个数组, Vector是线程安全的. 方法与ArrayList大体一致, 只是加上 synchronized 关键字, 保证线程安全, 下面 ...

随机推荐

  1. Scala 学习之路(十一)—— 模式匹配

    一.模式匹配 Scala支持模式匹配机制,可以代替swith语句.执行类型检查.以及支持析构表达式等. 1.1 更好的swith Scala不支持swith,可以使用模式匹配match...case语 ...

  2. 【设计模式】行为型05责任链模式(Chain of responsibility Pattern)

    学习地址:http://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html demo采用了DEBUG级别举例子,理解起 ...

  3. Git及基础命令的介绍以及如何向本地仓库添加文件

    在介绍Git的使用之前,我们得要先来了解一下Git.那么什么是Git? Git是一个版本管理工具(VCS),具有以下的特点: 分布式版本控制: 多个开发人员协调工作: 有效监听谁做的修改: 本地及远程 ...

  4. 在linux中,&和&&, |和|| ,&> 与 >的区别

    对应刚接触linux命令的小伙伴们来说,这些符号一定是很困扰的下面我们一起来看这些符号区别和用法 & 表示任务在后台执行,如要在后台运行 如: [root@localhost local]# ...

  5. Linux系统中sysctl命令详解

    sysctl命令用于运行时配置内核参数,这些参数位于/proc/sys目录下.sysctl配置与显示在/proc/sys目录中的内核参数.可以用sysctl来设置或重新设置联网功能,如IP转发.IP碎 ...

  6. 交叉编译多平台 FFmpeg 库并提取视频帧

    原文地址: 交叉编译多平台 FFmpeg 库并提取视频帧 交叉编译多平台 FFmpeg 库并提取视频帧 本文档适用于 x86 平台编译 armeabi.armeabi-v7a.arm64-v8a.x8 ...

  7. 微服务-springcloud学习资料链接

    API文档:https://springcloud.cc/spring-cloud-dalston.html#_spring_cloud_netflix 中文社区:http://springcloud ...

  8. django基础知识之csrf:

    csrf 全称Cross Site Request Forgery,跨站请求伪造 某些恶意网站上包含链接.表单按钮或者JavaScript,它们会利用登录过的用户在浏览器中的认证信息试图在你的网站上完 ...

  9. TCP/IP协议、三次握手、四次挥手

    1.什么是TCP/IP协议 TCP/IP 是一类协议系统,它是用于网络通信的一套协议集合. 传统上来说 TCP/IP 被认为是一个四层协议 1) 网络接口层: 主要是指物理层次的一些接口,比如电缆等. ...

  10. Linux命令学习-mv命令

    Linux中,mv命令的全称是move,主要作用是移动文件或文件夹,类似于Windows下的剪切功能,同时还可以用于修改名字. 假设当前处于wintest用户的主目录,路径为 /home/wintes ...