中我们介绍了ArrayList。其实在ArrayList的源码注释中就明确的指出了ArrayList这个类大致的等于Vector除了ArrayList是不同步的。那么现在趁热打铁,我们开始学习一下Vector。
结构分析
RandomAccess
这个Vector同样也实现了RandomAccess这个标记类,同ArrayList一样,代表能够高效的实现随机访问。
存储结构
同上篇一样,我们也是先来看看Vector的属性
可以看到,属性相比ArrayList的少了,那现在我们来看看这几个东西是干啥的。
- elementData: 这个elementData的作用跟ArrayList中的一样,都是用来存储元素的,这个数组的长度也就是这个Vector的容量。
- elementCount: 这个和ArrayList中的size差不多都是用来记录存储元素的数量的,比如现在Vector中有2个元素,这个elemetnCount=2;
- capacityIncrement: 这个属性就有点意思了,我们可以发现ArrayList中没有跟这个类似的东西,其实在我个人认为这也是一个Vector与ArrayList之间的一个不同点。 那这个属性是用来干啥的呢? 从名字我们可以猜出大概,容量增量,其实就是扩容的时候用来定义扩容多少的,我们会在下面扩容的内容中详细解说。
很简单,属性就上面那三个。我们可以发现Vector的底层存储结构就是一个数组。
基本方法
对于Vector的基本方法,不做太多介绍,其实就是对数组的操作,主要,对于数组的移位操作使用的System.arraycopy来完成,还有一个特点相比较ArrayList来说就是他的许多方法都有一个关键字synchronized。这就是为什么说Vector是同步的原因。我们看一下下面的图来体会一下:
subList
我们重点说一下subList方法,同时也是对ArrayList的一个补充。
subList返回的List是基于这个Vector或者ArrayList的的,也就是说,对subList返回的List进行的操作的结果最后会反映到源Vector或ArrayList上的,我们用代码来体会一下:
public class TestMain { public static void main(String[] args){ System.out.println("===============ArrayList================="); Listlist = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5")); List subList = list.subList(0,2); subList.add("我是subList插入的"); list.forEach(value ->System.out.print(value+" ,") ); System.out.println(); System.out.println("===============Vector=================="); Vector vector = new Vector<>(Arrays.asList("1", "2", "3", "4", "5")); List subVector = vector.subList(0,2); subVector.add("我是subVector插入的"); vector.forEach(value ->System.out.print(value+" ,")); }}复制代码
运行结果如下:
扩容机制
有上一节的铺垫,我们不做太多无用的的查看,直接看扩容的核心代码:
这就是Vector扩容的核心代码,看到与ArrayList的大同小异,不过这里确实多了一个这个东西,
在计算新的容量的时候,看了capacityIncrement的值是不是大于0,这个就是我们所说Vector与ArrayList扩容的不同处了,Vector可以自定义增长系数,控制需要扩容时增长的容量大小。当没有指定时默认增长为原来的两倍,与ArrayList一样,由于数组不能动态增大,所以是使用Arrays.copyOf重新生成了一个数组。
总结
- Vector内部使用数组存储元素,由于在方法时加了synchronized,所以性能比ArrayList低,但是是线程安全的。
- Vector扩容机制与ArrayList有些不同,不同之处在于Vector可以指定增长系数capacityIncrement,当不指定这个增长系数或者capacityIncrement为0的情况下默认扩容为原来的两倍。