对JAVA的Vector的深入理解

昨天我们从源码分析了ArrayList的底层实现原理,今天我们来从源码层面分析一下JAVA中与ArrayList及其类似的Vector对象的底层实现原理。来探究一下为什么JAVA这两种很相似的容器之间的异同。假如要了解ArrayList的底层原理可以看我昨天写的文章。

对JAVA的ArrayList的深入理解。icon-default.png?t=N7T8https://blog.csdn.net/weixin_61854715/article/details/140246703?spm=1001.2014.3001.5502

首先我们从两者的构造方法结构来初步观察两个对象的区别:

我们发现Vector多了一种构造方法Vector(int,int).我们稍后再看这个多出来的构造方法,先将参数类似的构造方法进行比较。

首先对比无参构造方法:

昨天我们已经解释了ArrayList的无参构造方法是将自己的内部一个数据成员elementData指向为一个空的Object数组对象,现在我们来仔细分析一下Vector的无参构造方法,Vector的无参构造方法调用了构造方法Vector(int),我们来分析一下Vector(int)构造方法的源码:

我们发现Vector(int)构造方法又调用了两个参数的构造方法Vector(int,int),我们继续来分析Vector(int,int)构造方法的源码:

我们发现Vector(int,int)首先调用了父类的无参构造方法,那么Vector的父类是什么呢?我们通过查看源码知道Vector的父类是AbstractList。

我们来查看AbstractList的无参构造方法,

发现这个方法并没有具体的操作,只是为了初始化父类,我们回到Vector(int,int)构造方法

在调用完父类的构造方法后,该方法进行了参数检查initialCapacity,假如initialCapacity小于0,抛出IllegalArgumentException的异常。接着我们看到了Vector像ArrayList一样初始化容量为initialCapacity的Object数组指向数据成员elementData。但很明显我们也可以看到Vector多了一个初始化参数capacityIncrement,这个是在ArrayList中没有的,我们看一看数据成员capacityIncrement具体是什么,

从这个变量的注释我们可以知道这个变量是干嘛用的,这个变量是用来定义每次我们加入元素超过数组容量后我们扩大数组的变化量,为了更加确定这个结论,我们来看一下Vector的add()方法来看一下Vector是如何添加元素的:

,我们发现了第一个关于modCount变量的介绍可以看我另一篇文章的最底下的补充知识:

深入理解JAVA的LinkedList

我们接着来分析ensureCapacityHelper函数的源码:

发现这个方法可以用来判断是否需要给Vector进行扩容的,假如需要扩容就调用grow方法,我们在来看grow方法的源码:

grow方法先记录了扩容前的数组长度,记录为oldCapacity,,接着开始计算新数组扩容的容量,我们发现新数组的容量是如何计算的呢,我们发现假如我们在调用Vector(int,int)构造函数的时候指定了capacityIncrement为了一个大于0的值的时候,计算新数组的容量就是老数组容量oldCapacity+capacityIncrement的和,假如我们没指定capacityIncrement或者将其指定为一个<=0的值,计算新数组的容量就是老数组容量oldCapacity * 2,自此我们可以看到Vector(int,int)构造方法使得我们可以指定Vector扩容时候的增量,而ArrayList并没有提供这个功能。我们继续阅读下面的源码,接下来该方法判断了扩充后的容量是否足够,假如不够,我们就将扩充的新容量设置为我们需要的最小容量,newCapacity=minCapacity,然后判断了newCapacity是否超过了Max_Array_Size。

通过源码我们发现Max_Array_Size的值是最大整数值-8,假如newCapacity大于了这个数就调用hugeCapacity方法:

这个方法是用来判断一个数是否超过了最大整数值的,假如超过了就返回Integer的最大值,否则就返回Max_Array_Size,这让我们知道了无论是Vector还是ArrayList等一系列数组对象是有一个最大容量的,即整数最大值,假如超过了这个数,Java将会抛出一个ArrayIndexOutOfBoundsException异常。我们在回到grow方法,grow方法的最后一句是Arrays.copyof方法,这个方法的本质是向内存申请一个指定容量的数组对象,具体源码分析在我写的下面的文章已详细分析,这里不在赘述。

深入理解JAVA的ArrayListicon-default.png?t=N7T8https://blog.csdn.net/weixin_61854715/article/details/140246703?spm=1001.2014.3001.5502

分析完这些之后我们回到Vector我们构造方法本质上就是一个构造方法Vector(int,int)

及我们可以指定Vector扩容时候的增量,这个是ArrayList对象所不具备的功能。我们在分析Vector的最后一个构造方法,

我们发现和ArrayList的类似的构造方法几乎完全一致,想要了解原理的同学可以读我上面的链接文章来具体了解这个方法的详细实现原理。

比较完ArrayList和Vector的构造方法时候我们已经发现功能上一个的不同,即ArrayList无法指定扩容时候的增量,我们平时也一定听过Vector是线程安全的,那么它是如何保证线程安全的呢?

我们发现Vector在对外提供的公有方法中添加了synchronized关键字,保证了线程安全性,而ArrayList中并没有,这便是Vector和ArrayList的第二个差别。尽管Vector保证了线程安全性,但是使用Vector还是ArrayList还是要根据具体情况而定,假如业务逻辑并不存在线程争抢资源的情况我们还是使用ArrayList,因为ArrayList没有加锁,所有ArrayList的性能是远高于Vector的。

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值