前言
在Java中集合使用的频率还是非常高、导致面试的常见问题、网上大部分的都有各种大佬做讲解的博客、本篇文章是根据网上资料、做的一个小总结。
JAVA版本1.8
上图为简图、具体基础图可以去idea中查看继承关系快捷键:ctrl+alt+u
从上图可以看到他顶级是Collection接口、接口方法说明所以说Vector实现了Collection接口中的方法。
抛出问题
- Vector是一个线程安全的集合为什么?
Vector集合说明
创建一个Vector集合对象
Vector<Integer> list = new Vector<>();
List<Integer> list = new Vector<>();
// 创建一个集合、形式为多态、父类 = new 子类实现();
什么是多态:编译看左、运行看右。
属性
protected Object[] elementDatae; // 数组缓存区、说白了就是存放数据的地方
protected int elementCount; // 存放在elementData中的数据个数
protected int capacityIncrement; // Vector容量自动计算的量
构造器
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0) // 做了一个判断、判断初始容量是否小于0、如果小于则抛出一个非法容量的异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity]; // 创建对应大小的数组给elementData
this.capacityIncrement = capacityIncrement; // capacityIncrement用来做扩容的判断的条件
}
// 设置开始容量的大小构造
public Vector(int initialCapacity) {
this(initialCapacity, 0); // 然后又调用了新构造
}
// 无参构造
public Vector() {
this(10); // 调了一个有参构造、这个数作为数组的初始容量
}
public Vector(Collection<? extends E> c) { // 将一个集合中的数据拷贝到Vector集合中
elementData = c.toArray();
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
// 做为数据的拷贝赋值给elementData
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
对集合CRUD简单说明
增
public synchronized boolean add(E e) {
modCount++; // 作为修改操作的记录数、在使用迭代的时候做条件判断后抛出ConcurrentModificationException异常
ensureCapacityHelper(elementCount + 1);// 做扩充容量
elementData[elementCount++] = e; // 添加到数组
return true;
}
// ensureCapacityHelper 方法
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0) // 最小容量减去数组长度是否大于0
grow(minCapacity); // 扩充的关键方法
}
// grow方法做为扩容核心
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; // 获取实际容量
// 如果capacityIncrement大于0:int newCapacity = oldCapacity + capacityIncrement
// 否则int newCapacity = oldCapacity + oldCapacity
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity); // 扩充
if (newCapacity - minCapacity < 0) // 新容量减去最小容量 小于 0 这个判断的作用就是说明扩展后的新容量没有达到想要的容量大小、
newCapacity = minCapacity; // 如何将最小容量赋值给新容量
if (newCapacity - MAX_ARRAY_SIZE > 0) // 这里做了一个判断、容量大小超过默认最大容量时的判断
newCapacity = hugeCapacity(minCapacity); // 两种可能1、扩充更大的容量2、抛出一个内存溢出异常
elementData = Arrays.copyOf(elementData, newCapacity); // 拷贝数组赋值给数组缓存区
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow //最小容量小于0
throw new OutOfMemoryError(); // 抛出内存溢出异常
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE; // 返回更大的容量数量
}
小结:grow()方法做为Vector扩容核心、int newCapacity = oldCapacity + oldCapacity 简单理解是就10 + 10 = 20 、所以他的扩容是2倍、因为这个capacityIncrement > 0 添加不会成立。
删
public synchronized E remove(int index) {
modCount++; // 作为修改操作的记录数、在使用迭代的时候做条件判断后抛出ConcurrentModificationException异常
if (index >= elementCount) // 检查索引
throw new ArrayIndexOutOfBoundsException(index); // 抛出下标异常
E oldValue = elementData(index); // 获取元素内容
//新数组的长度(数量) = 数组数量 - 索引 - 1
int numMoved = elementCount - index - 1;
if (numMoved > 0) // 如果长度大于的0、就进行数组的复制。
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 帮助 垃圾回收(GC)
elementData[--elementCount] = null; // Let gc do its work
return oldValue; // 返回被删除的元素
}
改
public synchronized E set(int index, E element) {
if (index >= elementCount) // 检查索引
throw new ArrayIndexOutOfBoundsException(index); // 抛出下标异常
E oldValue = elementData(index); // 获取到旧数据的内容
elementData[index] = element; // 将新数据赋值给原下标
return oldValue; // 返回被替换前的数据
}
查
public synchronized E get(int index) {
if (index >= elementCount) // 检查索引
throw new ArrayIndexOutOfBoundsException(index); // 抛出下标异常
return elementData(index); // 获取对应下标数据
}
问题解决: Vector是一个线程安全的集合为什么?
synchronized:线程中的同步关键字用来修饰方法、作为同步方法、简单理解在多线程中是相斥、互不影响。 具体线程的知识、还请自行找相关的资料去学习。
Vector总结:
-
Vector和ArrayList源码差不多、默认容量都为10 、扩容的的倍数不同、Vector 2倍、ArrayList1.5倍、Vector是线程安全的集合而ArrayList是不安全的集合、他们的增删改都很消耗性能、ArrayList比Vector要快、因为因为ArrayList没有同步机制操作。
-
扩容方式
-
// Vector的 int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); //ArrayList的 int newCapacity = oldCapacity + (oldCapacity >> 1);
-
-
Vector是可以重复元素也可以存放null值、线程安全集合。