H5W3
当前位置:H5W3 > java > 正文

【Java】JDK源码分析-Vector

JDK源码分析-Vector

WriteOnRead发布于 今天 15:13

1. 概述

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

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

【Java】JDK源码分析-Vector

2. 代码分析

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

2.1 构造器

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);
}

2.2 扩容原理分析

我们仍从其 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。

3. 线程安全性

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

4. 小结

  1. 与 ArrayList 类似,Vector 也可以认为是「可变数组」;
  2. 扩容原理与 ArrayList 基本一致,只是新容量计算方式略有不同:指定增长容量时,新容量为旧容量 + 增长容量;否则扩容为旧容量的 2 倍;
  3. 线程安全的,实现方式简单(synchronized);
  4. 当前使用较少,这里仅学习其实现原理。

【Java】JDK源码分析-Vector

java后端
阅读 40发布于 今天 15:13
本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议
avatar

WriteOnRead

微信公众号:WriteOnRead。

1 声望
0 粉丝

0 条评论
得票时间

avatar

WriteOnRead

微信公众号:WriteOnRead。

1 声望
0 粉丝

宣传栏

1. 概述

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

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

【Java】JDK源码分析-Vector

2. 代码分析

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

2.1 构造器

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);
}

2.2 扩容原理分析

我们仍从其 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。

3. 线程安全性

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

4. 小结

  1. 与 ArrayList 类似,Vector 也可以认为是「可变数组」;
  2. 扩容原理与 ArrayList 基本一致,只是新容量计算方式略有不同:指定增长容量时,新容量为旧容量 + 增长容量;否则扩容为旧容量的 2 倍;
  3. 线程安全的,实现方式简单(synchronized);
  4. 当前使用较少,这里仅学习其实现原理。

【Java】JDK源码分析-Vector

本文地址:H5W3 » 【Java】JDK源码分析-Vector

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址