Java 集合深入理解 (四) :古老 的Vector
作者:互联网
Java 集合深入理解 (三) :java.util 包的集合中 fail-fast 快速失败机制
简介:
Vector是java集合框架在现在看来比较古老,和arraylist一样同样维护一个数组, 但通过加synchronized来保证线程安全,看起来源码和arraylist基本相同,还是有研究的价值,废话不多说先从注释开始理解
/**
* The {@code Vector} class implements a growable array of
* objects. Like an array, it contains components that can be
* accessed using an integer index. However, the size of a
* {@code Vector} can grow or shrink as needed to accommodate
* adding and removing items after the {@code Vector} has been created.
*
* <p>Each vector tries to optimize storage management by maintaining a
* {@code capacity} and a {@code capacityIncrement}. The
* {@code capacity} is always at least as large as the vector
* size; it is usually larger because as components are added to the
* vector, the vector's storage increases in chunks the size of
* {@code capacityIncrement}. An application can increase the
* capacity of a vector before inserting a large number of
* components; this reduces the amount of incremental reallocation.
*
* <p><a name="fail-fast">
* The iterators returned by this class's {@link #iterator() iterator} and
* {@link #listIterator(int) listIterator} methods are <em>fail-fast</em></a>:
* if the vector is structurally modified at any time after the iterator is
* created, in any way except through the iterator's own
* {@link ListIterator#remove() remove} or
* {@link ListIterator#add(Object) add} methods, the iterator will throw a
* {@link ConcurrentModificationException}. Thus, in the face of
* concurrent modification, the iterator fails quickly and cleanly, rather
* than risking arbitrary, non-deterministic behavior at an undetermined
* time in the future. The {@link Enumeration Enumerations} returned by
* the {@link #elements() elements} method are <em>not</em> fail-fast.
*
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification. Fail-fast iterators
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>the fail-fast behavior of iterators
* should be used only to detect bugs.</i>
*
* <p>As of the Java 2 platform v1.2, this class was retrofitted to
* implement the {@link List} interface, making it a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>. Unlike the new collection
* implementations, {@code Vector} is synchronized. If a thread-safe
* implementation is not needed, it is recommended to use {@link
* ArrayList} in place of {@code Vector}.
*
* @author Lee Boynton
* @author Jonathan Payne
* @see Collection
* @see LinkedList
* @since JDK1.0
*/
翻译后
/**
*{@code Vector}类实现了一个可增长的对象。与数组一样,它包含可以使用整数索引访问。然而,一个
*{@code Vector}可以根据需要增长或收缩以适应在创建{@code Vector}之后添加和删除项。<p>每个向量都试图通过维护
*{@code capacity}和{@code capacityIncrement}。这个{@code capacity}总是至少和向量一样大尺寸;它通常更大,因为组件添加到
*向量,向量的存储以块的大小增加{@code capacityIncrement}。应用程序可以提高
*在插入大量数据之前向量的容量部件;这减少了增量再分配的数量。
*<p><a name=“fail fast”>java中的fail-fast(快速失败)机制这个类的{@link#iterator()iterator}和
*{@link#lisiterator(int)lisiterator}方法是快速失败的:如果在迭代器运行后的任何时候对向量进行了结构修改
*以任何方式创建,除了通过迭代器自己的{@link ListIterator#remove()remove}或
*{@link ListIterator#add(Object)add}方法,迭代器将抛出{@link ConcurrentModificationException}。因此,面对
*并发修改时,迭代器会快速而干净地失败,而不是而不是冒着武断的、不确定的行为
*未来的时间。返回的{@link Enumerations}{@link#elements()elements}方法是<em>not</em>fail fast。
*<p>请注意,不能保证迭代器的快速失败行为一般说来,不可能在未来作出任何硬性保证
*存在未同步的并发修改。失败快速迭代器
*尽最大努力抛出{@code ConcurrentModificationException}。
*因此,编写依赖于此的程序是错误的其正确性例外:<i>迭代器的快速失败行为
*应仅用于检测错误。</i>
*<p>从Java2平台v1.2开始,这个类被改进为
*实现{@link List}接口,使其成为
*<a href=“{@docRoot}/./technotes/guides/collections/index.html”>
*Java集合框架</a>。与新系列不同
*实现时,{@code Vector}是同步的。如果线程安全
*不需要实现,建议使用{@link
*ArrayList}代替{@code Vector}。
* @author Lee Boynton
* @author Jonathan Payne
* @see Collection
* @see LinkedList
* @since JDK1.0
*/
整段注释翻译 主要体现在 vector是动态扩容、并且为保证数据的安全使用快速失败机制,并且建议我们如果线程安全不需要实现,则使用arraylist。
从接口来看,和arraylist的继承和实现是一致的,都是实现AbstractList 并获得一些sublist等方法,以及实现list接口 实现 add方法等
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
/**
*将向量的分量放入其中的数组缓冲区已存储。向量的容量就是这个数组缓冲区的长度,
*并且至少足够大以包含向量的所有元素。<p>向量中最后一个元素后面的任何数组元素都为空。
*/
protected Object[] elementData;
/**
*此{@code Vector}对象中有效组件的数目。组件{@code elementData[0]}到
*{@code elementData[elementCount-1]}是实际项。@序列号
*/
protected int elementCount;
/**
*向量容量自动计算的量当其大小大于其容量时递增。如果容量增量小于或等于零,则容量
*每次需要生长时,载体的体积都会加倍。
*@序列号
*/
protected int capacityIncrement;
下面是arraylist中的成员变量,
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
对比arraylist确实是少了很多优化的地方,比如说序列化优化的transient,根据不同构造方法构造不同的数组的DEFAULTCAPACITY_EMPTY_ELEMENTDATA,以及默认长度DEFAULT_CAPACITY 等等;我想应该是作者也应该没优化该类了
/**
* 构造一个具有指定初始容量和容量增量。
*
* @param initialCapacity initialCapacity向量的初始容量
* @param capacityIncrement capacityIncrement容量的增量
* 向量溢出时增加
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
/**
* Constructs an empty vector so that its internal data array
* has size {@code 10} and its standard capacity increment is
* zero.
*/
public Vector() {
this(10);
}
就是简单的new了一个数组,指定初始化容量机容量增量 ,直接指定好 10的容量
通过关键方法去理解一下,add方法 ,首先通过 synchronized 关键字去保证多线程下数据的安全,modCount 记录好每次操作次数,在ensureCapacityHelper 中判断容量是否超出,如果超出则直接扩大一倍在来对比数据,扩大一倍还是不够,这选择扩大到增加数据的大小 ,如果小于 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
则直接使用 MAX_VALUE ,最后采用 Arrays.copyOf 进行扩容
/**
* 将指定的元素追加到此向量的末尾。
*
* @param e element to be appended to this Vector
* @return {@code true} (as specified by {@link Collection#add})
* @since 1.2
*/
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
/**
*这实现了ensureCapacity的非同步语义。此类中的同步方法可以在内部调用一种在不增加生产成本的情 况下保证生产能力的方法额外的同步。
*
* @see #ensureCapacity(int)
*/
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);
}
删除此向量中指定元素的第一个匹配项如果向量不包含元素,返回是否成功。
/**
*删除此向量中指定元素的第一个匹配项如果向量不包含元素,则它是不变的。更多形式上,移除索引i最低的元 素
*{@code(o==null?get(i)==null:o.equals(get(i)))}(如果是这样的话)元素存在)。
* @param o 要从此向量中删除的元素(如果存在)
* @return 如果向量包含指定的元素,则为true
* @since 1.2
*/
public boolean remove(Object o) {
return removeElement(o);
}
/**
*删除参数的第一个(索引最低的)匹配项从这个向量。如果在这个向量中找到对象,每个向量中索引大于或等于
*对象的索引向下移动,使索引变小
*比以前的价值要高。
*
* <p>This method is identical in functionality to the
* {@link #remove(Object)} method (which is part of the
* {@link List} interface).
*
* @param obj the component to be removed
* @return {@code true} if the argument was a component of this
* vector; {@code false} otherwise.
*/
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
java.util集合结构图
最后:vector都是采用synchronized 作关键字通过对象锁来保证数据安全,这部分我解析的比较少,因为大部分和arraylist差不多,并且实现理解更简单,具体还是看arraylist中的解析
标签:capacityIncrement,code,Java,int,Vector,link,集合,向量 来源: https://blog.csdn.net/qq_33373609/article/details/116465378