Vector源码分析

Vector是一个类似于ArrayList的集合,但是又有所不同,我们来分析一下他的源码。

 

分析源码之前, 我们先看看Vector有什么特点,然后再根据源码去分析为什么他会有这些特点。

  1. Vector类似于ArrayList,也就是说内部也是维护一个数组。
  2. Vector是同步访问的。
  3. Vector的大小是动态的,也就是说是可扩容的。

 

Vector类似ArrayList

         这个特点很简单,直接看源码:

Vector源码分析

         很明显,这里是一个Object类型的数组,名称为elementData,这个数组的大小即是集合的大小。

Vector是同步访问的

         既然是访问,那我们看看get()方法就知道了。

Vector源码分析

         方法标签上有synchronized关键字修饰,说明是同步访问的。

Vector大小是动态的

增加

         大小发生动态变化的时候一般都是增删操作的时候,我们先看增加操作。

Vector源码分析

         显然,增加操作也是同步的,并且在增加之前做了容量的判断,所以我们继续看看ensureCapacityHelper()方法是如何动态处理容量的。值得注意的是,这里传入的参数是elementCount+1,也就是现有容量加上即将要增加的一个元素的容量,也就是即将需要的容量。

Vector源码分析

         即将需要的容量在这里被命名为minCapacity,可以理解成现在需要的最小容量。所以首先做了一个判断,如果需要的最小容量大于集合现在的大小,那么就要扩容,执行grow()方法,该方法将需要的最小容量作为参数传过去。

Vector源码分析

         这个方法中有个capacityIncrement,这个变量是指每次扩容的大小,有个构造方法可以指定这个参数,如果没有使用这个构造方法,默认值为0。

         所以这里确定扩容后新的集合大小的方式是,如果指定了capacityIncrement,那么就扩容指定大小,如果没有指定,就将容量扩大为原来的2倍。

         确定了扩容后的大小之后还要判断是否大于当前需要的最小容量、是否超过了MAX_ARRAY_SIZE这个常量。

         如果大于MAX_ARRAY_SIZE常量,就执行hugeCapacity()方法,否则,就用Arrays.copyOf()复制一个数组,也就是返回了一个新的数组,其中的数据和之前一样,只有数组大小不一样。所以我们可以把关注点放在hugeCapacity()方法上,看看做了什么。

Vector源码分析

         这个方法也很简单,判断一下需要的最小空间是否溢出,如果没有溢出,并且需要的最小空间确实要大于MAX_ARRAY_SIZE的话,就将新的集合大小设置为Integer的最大值,否则就设置为MAX_ARRAY_SIZE,如果代码从我们这次阅读的路径过来,是不可能执行到“否则”的。

删除

         增加操作是导致扩容的直接原因,那删除操作是否会导致缩容呢?

Vector源码分析

         答案是不会的,删除操作只是将删除位置的元素右边的元素全部左移,然后将最后一个位置的引用置为null,等待垃圾回收机制回收即可。

     问题

为什么MAX_ARRAY_SIZE = Integer.MAX_VALUE – 8?

         没有找到一个合理的解释,最合理的是说数组类要存储类型信息,但是为什么真的超过了,又能扩容到Integer的最大值呢。

         附上答案连接:https://*.com/questions/35756277/why-the-maximum-array-size-of-arraylist-is-integer-max-value-8