Vector源码笔记 — 普通增删查改
先看一下类关系图:
Vector这个玩意,emmm 实际开发中一次都没用过,但是面试题不少,还是好好的啃啃源码:
先上类简介:
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, SerializableVector类实现了可扩展的对象数组。 像数组一样,它包含可以使用整数索引访问的组件。 但是, Vector的大小可以根据需要增长或缩小,以适应在创建Vector之后添加和删除项目。
每个向量尝试通过维护capacity和capacityIncrement优化存储capacityIncrement 。 capacity总是至少与矢量大小一样大; 通常较大,因为当向量中添加组分时,向量的存储空间大小capacityIncrement 。 应用程序可以在插入大量组件之前增加向量的容量; 这减少了增量重新分配的数量。
The iterators returned by this class's个 iterator和listIterator方法是快速失败的 :如果向量在任何时间从结构上修改创建迭代器之后,以任何方式除非通过迭代器自身remove种或add方法,迭代器都将抛出一个ConcurrentModificationException 。 因此,面对并发修改,迭代器将快速而干净地失败,而不是在未来未确定的时间冒着任意的非确定性行为。 由elements返回的Enumerations 不是故障快速的。
请注意,迭代器的故障快速行为无法保证,因为一般来说,在不同步并发修改的情况下,无法做出任何硬性保证。 失败快速迭代器尽力投入ConcurrentModificationException 。 因此,编写依赖于此异常的程序的正确性将是错误的:迭代器的故障快速行为应仅用于检测错误。
从Java 2平台v1.2,这个类被改造为实现List接口,使其成为成员Java Collections Framework 。 与新集合实现不同, Vector是同步的。 如果不需要线程安全的实现,建议使用ArrayList代替Vector 。
这里是JDK1.8的帮助手册介绍,可以了解到这个东西底层是一个数组,然后同同步的,线程安全的
无参构造方法
不啰嗦直接看构造:
/**
构造一个空向量,使其内部数据数组的大小为 10 ,标准容量增量为零。
* Constructs an empty vector so that its internal data array
* has size {@code 10} and its standard capacity increment is
* zero.
*/
public Vector() {
//这里就是调用有参构造方法,初始化一个长度为10的数组
this(10);
}
/**
构造具有指定初始容量并且其容量增量等于零的空向量。
* Constructs an empty vector with the specified initial capacity and
* with its capacity increment equal to zero.
*
* @param initialCapacity the initial capacity of the vector
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
/**
构造具有指定的初始容量和容量增量的空向量。
* Constructs an empty vector with the specified initial capacity and
* capacity increment.
*
* @param initialCapacity the initial capacity of the vector
* @param capacityIncrement the amount by which the capacity is
* increased when the vector overflows
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public Vector(int initialCapacity, int capacityIncrement) {
//这里调用了父类的空参构造方法,里面啥也没有就不看了
super();
//如果数组容量小于0 直接抛出夜场
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//创建一个容量为多少的数组 ,默认10
this.elementData = new Object[initialCapacity];
//这个capacityIncrement 属性具体不知道干嘛的,看看api文档介绍然后留意一下
// 当矢量的大小大于其容量时,矢量的容量自动增加的量。
this.capacityIncrement = capacityIncrement;
}
增
接着添加一个数据:
Vector<String> vector = new Vector<>();
vector.add("Hello World");
进入看源码:
/**
将指定的元素追加到此Vector的末尾。
* Appends the specified element to the end of this Vector.
*
* @param e element to be appended to this Vector
* @return {@code true} (as specified by {@link Collection#add})
* @since 1.2
*/
//这里就可以看出Vector是线程安全的
public synchronized boolean add(E e) {
//此列表已被 结构修改的次数。 这个属性是父类AbstractList的属性
modCount++;
//这个方法检测添加一个元素后是否超出当前数组容量,如果超出执行扩容
ensureCapacityHelper(elementCount + 1);
//添加到数组
elementData[elementCount++] = e;
return true;
}
/**
这实现了保证容量。同步此类中的方法可以在内部调用thismethod以确保容量,而不会产生额外的同步开销。
* This implements the unsynchronized semantics of ensureCapacity.
* Synchronized methods in this class can internally call this
* method for ensuring capacity without incurring the cost of an
* extra synchronization.
*
* @see #ensureCapacity(int)
*/
//这个方法检测添加一个元素后是否超出当前数组容量,如果超出执行扩容
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
//判断当前添加元素之后是否超出数组长度 如果是则扩容
if (minCapacity - elementData.length > 0)
//扩容
grow(minCapacity);
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
//int类型最大值 - 8
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//扩容
private void grow(int minCapacity) {
// overflow-conscious code
//记录旧的数组长度
int oldCapacity = elementData.length;
//这里可以看到capacityIncrement 这个属性的作用了,这个属性就是代表每一次扩容扩充多少
//如果没有自定义扩容容量这直接扩充两倍
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
//如果新的容量还是小于当前元素个数 那么直接把元素个数作为新数组长度
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果新的数组长度大于int类型最大值 - 8
if (newCapacity - MAX_ARRAY_SIZE > 0)
//如果超过Int类型所接纳容量则抛出异常 如果超过Int类型最大值 - 8则返回 int 类型最大值 如果没有超过则返回 int 最大值 -8
newCapacity = hugeCapacity(minCapacity);
//复制一份新数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
//
private static int hugeCapacity(int minCapacity) {
//如果当前容量小于 0 这里其实判断是容量是否超过Int类型容量 如果超过则抛出异常
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//如果 大于 int 类型最大值-8 则返回int类型最大值,如果不是则返回int类型最大值-8
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
查
Vector<String> vector = new Vector<>();
vector.add("Hello World");
vector.add("Hello World 001");
vector.add("Hello World 002");
vector.add("Hello World 003");
System.out.println(vector.get(0));
看源码:
/**
* Returns the element at the specified position in this Vector.
*
* @param index index of the element to return
* @return object at the specified index
* @throws ArrayIndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= size()})
* @since 1.2
*/
public synchronized E get(int index) {
//如果查找的索引 大于 等于当前数组元素个数 则抛出异常
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
//返回元素
return elementData(index);
}
// Positional Access Operations
@SuppressWarnings("unchecked")
//返回元素
E elementData(int index) {
return (E) elementData[index];
}
改
Vector<String> vector = new Vector<>();
vector.add("Hello World");
vector.add("Hello World 001");
vector.add("Hello World 002");
vector.add("Hello World 003");
vector.set(0,"Hello World 修改");
System.out.println(vector.get(0));
看源码:
/**
* Replaces the element at the specified position in this Vector with the
* specified element.
*
* @param index index of the element to replace
* @param element element to be stored at the specified position
* @return the element previously at the specified position
* @throws ArrayIndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= size()})
* @since 1.2
*/
//修改值返回就值
public synchronized E set(int index, E element) {
//判断当前索引是否超过元素个数
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
//记录就值
E oldValue = elementData(index);
//设置新值
elementData[index] = element;
//返回就值
return oldValue;
}
删
Vector<String> vector = new Vector<>();
vector.add("Hello World");
vector.add("Hello World 001");
vector.add("Hello World 002");
vector.add("Hello World 003");
vector.set(0,"Hello World 修改");
vector.remove(0);
System.out.println(vector.get(0));
看源码:
/**
* Removes the element at the specified position in this Vector.
* Shifts any subsequent elements to the left (subtracts one from their
* indices). Returns the element that was removed from the Vector.
*
* @throws ArrayIndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= size()})
* @param index the index of the element to be removed
* @return element that was removed
* @since 1.2
*/
//删除指定索引值返回旧值
public synchronized E remove(int index) {
//操作次数增加一次
modCount++;
//
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
//获取旧的数组
E oldValue = elementData(index);
// 这个是获得下一个元素的索引
int numMoved = elementCount - index - 1;
if (numMoved > 0)
//是是个本地方法意思大概就是将指定元素移到最后一个,指定元素之后元素往前进一
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//移除某元素
elementData[--elementCount] = null; // Let gc do its work
//返回旧值
return oldValue;
}