ArrayList和Vector的区别

来源:互联网 发布:openstack入门 知乎 编辑:程序博客网 时间:2024/04/29 11:37

Vector和ArrayList非常相似,两者都是用来表示可变数组,内部元素的存储都是通过数组来实现,可以随机的访问某个元素。

两者的主要区别是Vector的方法带有synchronized标志,各方法的访问是同步的,因此,Vector能够支持多线程,但是相应地效率比较低;ArrayList的方法没有synchronized标志,不是线程安全的。还有个比较小的差异是Vector在容量不够时,选择 size * 2扩容;ArrayList选择 size * 3/2 + 1扩容。

下面先来看下ArrayList的源码:

Java代码  

1. public class ArrayList<E> extends AbstractList<E>  

2.         implements List<E>, RandomAccess, Cloneable, java.io.Serializable  

 RandomAccess: 这个是标记接口,没有需要实现的方法,声明ArrayList可以随机访问

Cloneable:ArrayList支持拷贝

Serializable: ArrayList支持序列化

ArrayList定义了如下的数组对象:

Java代码  

1. /** 

2.      * The array buffer into which the elements of the ArrayList are stored. 

3.      * The capacity of the ArrayList is the length of this array buffer. 

4.      */  

5.     private transient Object[] elementData;  

 ArrayList使用elementData数组来缓存元素,使用transient关键字说明该数组对象不会被默认序列化,,开始很困惑,既然声明了ArrayList是可序列化的,为什么数组对象又声明为不能被序列化的?

Java代码  

1.  /** 

2.      * Save the state of the <tt>ArrayList</tt> instance to a stream (that 

3.      * is, serialize it). 

4.      * 

5.      * @serialData The length of the array backing the <tt>ArrayList</tt> 

6.      *             instance is emitted (int), followed by all of its elements 

7.      *             (each an <tt>Object</tt>) in the proper order. 

8.      */  

9.     private void writeObject(java.io.ObjectOutputStream s)  

10.        throws java.io.IOException{  

11.    // Write out element count, and any hidden stuff  

12.    int expectedModCount = modCount;  

13.    s.defaultWriteObject();  

14.        // Write out array length  

15.        s.writeInt(elementData.length);  

16.    // Write out all elements in the proper order.  

17.    for (int i=0; i<size; i++)  

18.            s.writeObject(elementData[i]);  

19.    if (modCount != expectedModCount) {  

20.            throw new ConcurrentModificationException();  

21.        }  

22.    }  

23./** 

24.     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, 

25.     * deserialize it). 

26.     */  

27.    private void readObject(java.io.ObjectInputStream s)  

28.        throws java.io.IOException, ClassNotFoundException {  

29.    // Read in size, and any hidden stuff  

30.    s.defaultReadObject();  

31.        // Read in array length and allocate array  

32.        int arrayLength = s.readInt();  

33.        Object[] a = elementData = new Object[arrayLength]; 

34.    // Read in all elements in the proper order.  

35.    for (int i=0; i<size; i++)  

36.            a[i] = s.readObject();  

37.    }  

 因为ArrayList自定义了writeObject和readObject的方法,在writeObject中循环elementData数组序列化ArrayList中的元素。 可是为啥要这么折腾呢 

Java代码  

1. public void ensureCapacity(int minCapacity) {  

2. modCount++;  

3. int oldCapacity = elementData.length;  

4. if (minCapacity > oldCapacity) {  

5.     Object oldData[] = elementData;  

6.     int newCapacity = (oldCapacity * 3)/2 + 1;  

7.         if (newCapacity < minCapacity)  

8.     newCapacity = minCapacity;  

9.            // minCapacity is usually close to size, so this is a win:  

10.           elementData = Arrays.copyOf(elementData, newCapacity);  

11.}  

12.   }  

 在创建ArrayList对象的时候,如果没有指定大小,默认ArrayList的size为10;在添加元素的时候,如果当前空间不足,会按照上面的ensureCapacity的方法来扩容,扩容后的大小是原先的1.5倍。因此elementData数组很可能没有放满,会有很多无效的null元素,默认的序列化会把无效的null元素也序列化,影响效率。

Java代码  

1.    public E get(int index) {  

2. RangeCheck(index);    

3. return (E) elementData[index];  

4.    }  

5.    public boolean add(E e) {  

6. ensureCapacity(size + 1);  // Increments modCount!!  

7. elementData[size++] = e;  

8. return true;  

9.    }   

10.   public E remove(int index) {  

11.RangeCheck(index);  

12.modCount++;  

13.E oldValue = (E) elementData[index];  

14.int numMoved = size - index - 1;  

15.if (numMoved > 0)  

16.    System.arraycopy(elementData, index+1, elementData, index,  

17.             numMoved);  

18.elementData[--size] = null// Let gc do its work  

19.return oldValue;  

20.   }  

 上面是ArrayList的常见的方法,可以看到,实质上就是做些数组的操作。

下面先来看下Vector的源码:

Java代码  

1. public class Vector<E>  

2.     extends AbstractList<E>  

3.     implements List<E>, RandomAccess, Cloneable, java.io.Serializable  

 Vector的声明跟ArrayList一样,也是实现了List<E>,RandomAccess, Cloneable, java.io.Serializable这几个接口。

Java代码  

1. private void ensureCapacityHelper(int minCapacity) {  

2.     int oldCapacity = elementData.length;  

3.     if (minCapacity > oldCapacity) {  

4.         Object[] oldData = elementData;  

5.         int newCapacity = (capacityIncrement > 0) ?  

6.         (oldCapacity + capacityIncrement) : (oldCapacity * 2);  

7.             if (newCapacity < minCapacity) {  

8.         newCapacity = minCapacity;  

9.         }  

10.            elementData = Arrays.copyOf(elementData, newCapacity);  

11.    }  

12.    }  

 上面是Vector的扩容方法,当空间不足时,会分配 size * 2的空间。

Java代码  

1. public synchronized E elementAt(int index) {  

2.     if (index >= elementCount) {  

3.         throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);  

4.     }  

5.         return (E)elementData[index];  

6.     }  

7.  public synchronized void addElement(E obj) {  

8.     modCount++;  

9.     ensureCapacityHelper(elementCount + 1);  

10.    elementData[elementCount++] = obj;  

11.    }  

12.public synchronized void removeElementAt(int index) {  

13.    modCount++;  

14.    if (index >= elementCount) {  

15.        throw new ArrayIndexOutOfBoundsException(index + " >= " +  

16.                             elementCount);  

17.    }  

18.    else if (index < 0) {  

19.        throw new ArrayIndexOutOfBoundsException(index);  

20.    }  

21.    int j = elementCount - index - 1;  

22.    if (j > 0) {  

23.        System.arraycopy(elementData, index + 1, elementData, index, j);  

24.    }  

25.    elementCount--;  

26.    elementData[elementCount] = null/* to let gc do its work */  

27.    }  

 上面是Vector的常见的方法,跟ArrayList的主要区别是在方法上加了synchronized关键字

0 0
原创粉丝点击