关于ArrayList和Vector空间利用率的一点探索

来源:互联网 发布:陈志武的课怎么样 知乎 编辑:程序博客网 时间:2024/05/17 00:17

看到一篇java方面的文章其中提到ArrayList和Vector俩容器,文章作者提到Vector的空间利用率比ArrayList要大,最有意思的是他说Vector的空间利用率能达到100%。看到这里我就醉了,想着基于java数组实现的Vector容器利用率能达到100%,要想达到每次增加一个元素,利用率能达到100%,岂不是每次Vector容量的扩增只能是1,否则怎么可能每次扩增利用率能达到100%。想到这里,于是我查看了下ArrayList和Vector的源码。

关于Vector底层数组容量扩增的源码:

public synchronized boolean add(E e) {    modCount++;    ensureCapacityHelper(elementCount + 1);    elementData[elementCount++] = e;    return true;}private void ensureCapacityHelper(int minCapacity) {    // overflow-conscious code    if (minCapacity - elementData.length > 0)        grow(minCapacity);}private void grow(int minCapacity) {    // overflow-conscious code    int oldCapacity = elementData.length;    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?                                     capacityIncrement : oldCapacity);//扩容    if (newCapacity - minCapacity < 0)        newCapacity = minCapacity;    if (newCapacity - MAX_ARRAY_SIZE > 0)        newCapacity = hugeCapacity(minCapacity);    elementData = Arrays.copyOf(elementData, newCapacity);}

从上可以轻易的看出如果没有指定初始增加容量capacityIncrement的值,那它为默认值0。

int newCapacity=oldCapacity+oldCapacity。在原有的基础上扩增一倍。查看源码可知Vector的初始容量为10,如果存储11个数那他的空间利用率为f = 11/(10*2)=55%、存储20个数f = 20/(10*2)=100%。

同理,下面我们来看下ArrayList的容量扩展代码:

public boolean add(E e) {    ensureCapacityInternal(size + 1);  // Increments modCount!!    elementData[size++] = e;    return true;}private void ensureCapacityInternal(int minCapacity) {    if (elementData == EMPTY_ELEMENTDATA) {        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);    }    ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) {    modCount++;    // overflow-conscious code    if (minCapacity - elementData.length > 0)        grow(minCapacity);}private void grow(int minCapacity) {    // overflow-conscious code    int oldCapacity = elementData.length;    int newCapacity = oldCapacity + (oldCapacity >> 1);//扩增容量    if (newCapacity - minCapacity < 0)        newCapacity = minCapacity;    if (newCapacity - MAX_ARRAY_SIZE > 0)        newCapacity = hugeCapacity(minCapacity);    // minCapacity is usually close to size, so this is a win:    elementData = Arrays.copyOf(elementData, newCapacity);}

从上可以得知newCapacity = oldCapacity+oldCapacity/2;也就是说如果容量需要扩增时每次只能扩增他当前容量的50%。而Vector是扩增100%。所以我们来看看它的容量利用率。查源码得知ArrayList的初始容量也是10。假如存储11个数到ArrayList那利用率f = 11/(10+10*50%)=73.3%,如果是增加20则利用率为f=20/(15+15*50%)=90%,刚好增加10个那肯定是100%。

由上数据分析可知:ArrayList和Vector的空间利用率其实是没有比较的意义的。不存在说Vector的空间利用率比ArrayList大,更不可能说Vector的空间利用率是100%,只能说有时它能达到100%。但查看源码得知,不管是ArrayList还是Vector他们都可以在初始化的时候指定对应的初始增加容量,所以当我们知道需要存储的数据是多少时,我们可以自己指定需要增加的容量,一步到位。不需要让其自身去增加,降低性能。

Vector和ArrayList的区别是ArrayList它每次是增加自身50%的容量而Vector是增加100%,所以当我们处理的数据量较大时使用Vector存储效率更高因为他容量扩增的次数比ArrayList要少。所以很多书上说Vector是大容量容器而List接口下的实现类则是小容量容器这是有一定的道理的。而且Vector是支持线程同步的,所以多线程并发访问时Vector是安全的,但是ArrayList则不支持线程同步,需要人为的去定义才能使ArrayList支持线程同步。从这点上看,Vector确实比ArrayList有优势,但是有利也有弊。这样一来就降低了Vector的效率。所以在开发过程中需要找他它俩者的平衡点再选择使用哪个容器则是最好的。谁都不比谁优劣。

0 0
原创粉丝点击