代码改变世界

此Vector非彼Vector

2004-08-05 15:51  FantasySoft  阅读(...)  评论(...编辑  收藏

        在学习STL的过程中,我发现了一个熟悉的面孔——Vector。之所以熟悉,是因为Vector是Java核心类库中的Collection container的一种,然而在我近一年的开发历程当中,我从来都没有使用过Vector,甚至对其几乎是一无所知,只是知道这是JDK中遗留的Collection container,而且在开发过程中也不提倡使用它。花心的我在看着STL的Vector的时候,心里还是惦记着我那可爱的Java情人[1]。于是,我翻出了JDK的document,翻出了Vector的source code,去看个究竟。
        噢,Vector原来就是动态数组啊,这不是跟STL中的Vector很类似吗?即使在Java核心类库当中,
ArrayList不也是动态数组吗?而STL并没有跟ArrayList相match的东东啊(至少看字面上就没有)。那么在Java中Vector与ArrayList有什么区别呢?那么Java中的Vector与STL中Vector呢?
       在Java当中,Vector与ArrayList都是AbstractList派生的子类,在很多方面它们是很类似的:
       1、实现了动态增长的数组;
       2、通过对象数组(Object[])来实现数据的存储,因此它们都无法容纳原始类型(primitive type),如 int类型的数据;
       而它们的区别:
       1、正如JDK上所说的那样(This class is roughly equivalent to Vector, except that it is unsynchronized),主要在同步性上:Vector是同步的,而ArrayList是非同步的。由于实现同步,在效率上Vector要比ArrayList要低。
       2、除此之外,它们在数组的动态增长的策略上也是不同。往Vector增加一个元素的时候,如果Vector的容量(capacity)不足的时候,将会从新创建一个对象数组,请看下面来自 JDK的源代码:

private void ensureCapacityHelper(int minCapacity) {
 
int oldCapacity =
 elementData.length;
 
if (minCapacity > oldCapacity) 
{
     Object oldData[] 
=
 elementData;
     
int newCapacity = (capacityIncrement > 0?

  (oldCapacity 
+ capacityIncrement) : (oldCapacity * 2);
         
if (newCapacity < minCapacity) 
{
  newCapacity 
=
 minCapacity;
     }

     elementData 
= new Object[newCapacity];
     System.arraycopy(oldData, 
0, elementData, 0
, elementCount);
 }

}

        这里得特别说一下,如果使用不带参数的构造函数( Vector() )去创建一个Vector实例的话,capacityIncrement的初始值为0,而capacity为10。   
        而ArrayList在遇到capacity不足的时候,所创建的对象数组的capacity为newCapacity = (oldCapacity * 3)/2 + 1。我不赞同一些人所说的保存大量数据时候,就应该使用Vector。诚然,由于Vector采取的数组动态增长的策略,使得新创建的对象数组相对较大,减少了分配内存和数组拷贝的次数,但是这样带来的副作用是造成了内存空间的浪费;同时,我觉得应该尽可能少用不带参数的构造方法,在构造实例的同时为Vector或者ArrayList赋予合适的capacity才是最好的解决办法。
        3、Vector提供了比ArrayList丰富得多的函数。如Vector提供了
              修改某个索引值对应元素的方法:setElementAt(Object, int);
              在某个索引值前插入元素的方法:insertElementAt(Object,int);
              返回capacity的方法:capacity();
              ……
        相比之下,也许是因为同步造成的问题吧,否则我怎么都想不明白为什么不提倡使用Vector。同时,在比较ArrayList和Vector过程中,我也越发觉得泛型的强大了,最明显的就是ArrayList和Vector都使用对象数组去存储数据,编译器就无法对其进行类型检查了。至于STL中的Vector与Java中的Vector有什么区别,下次再续了。

        [1] Summary of function parameter