java集合系列04:Vector和Stack解析

Vectory

第1部分 Vector介绍

Vector简介

Vector 是矢量队列,它是JDK1.0版本添加的类。继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。
Vector 继承了AbstractList,实现了List;所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能
Vector 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。
Vector 实现了Cloneable接口,即实现clone()函数。它能被克隆。

和ArrayList不同,Vector中的操作是线程安全的

Vector的构造函数

Vector共有4个构造函数
// 默认构造函数
Vector()

// capacity是Vector的默认容量大小。当由于增加数据导致容量增加时,每次容量会增加一倍。
Vector(int capacity)

// capacity是Vector的默认容量大小,capacityIncrement是每次Vector容量增加时的增量值。
Vector(int capacity, int capacityIncrement)

// 创建一个包含collection的Vector
Vector(Collection<? extends E> collection)

第2部分 Vector数据结构


java.lang.Object
   ↳     java.util.AbstractCollection<E>
         ↳     java.util.AbstractList<E>
               ↳     java.util.Vector<E>

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}

 

Vector与Collection关系如下图

Vector的数据结构和ArrayList差不多,它包含了3个成员变量:elementData , elementCount, capacityIncrement

(01) elementData 是"Object[]类型的数组",它保存了添加到Vector中的元素

(02) elementCount 是动态数组的实际大小。

(03) capacityIncrement 是动态数组的增长系数。如果在创建Vector时,指定了capacityIncrement的大小;则,每次当Vector中动态数组容量增加时>,增加的大小都是capacityIncrement。

第3部分 Vector源码解析

    构造函数
public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }


public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }


 public Vector() {
        this(10);
    }  


 public Vector(Collection<? extends E> c) {
        elementData = c.toArray();
        elementCount = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
    }   

可以看到,Vector的默认初始容量大小是10(ArrayList为0)


    add(E e)
public synchronized boolean add(E e) {
        modCount++;
        //确保容量足够
        ensureCapacityHelper(elementCount + 1);
        //添加元素
        elementData[elementCount++] = e;
        return true;
    }

从上面代码可以看到,add()方法用synchronized关键字修饰,所以是线程安全的,ensureCapacityHelper()方法用于确保容量足够,不够时扩展容量,其实现如下:

可以看到,当需要扩容时,将调用grow()方法。

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时,那么newCapacity将会是两倍的oldCapacity

其余操作

其余操作与ArrayList类似,只不过每个方法都多了synchronized关键字,从而保证了Vector类的线程安全。

Stack

Stack类的实现比较简单,只是在Vector的基础上添加了一个方法,下面是Stack类的实现:

private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
public class Stack<E> extends Vector<E> {
    public E push(E item) {
        addElement(item);

        return item;
    }
    
    public synchronized E pop() {
        E       obj;
        int     len = size();

        obj = peek();
        removeElementAt(len - 1);

        return obj;
    }

    public synchronized E peek() {
        int     len = size();

        if (len == 0)
            throw new 
        EmptyStackException();
        return elementAt(len - 1);
    }
    public boolean empty() {
        return size() == 0;
    }
     public synchronized int search(Object o) {
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }
     private static final long serialVersionUID = 1224463164541339165L;
}

从上面的代码可以看到,Stack内部一共五个方法,其中三个方法都加了synchronized关键字,是线程安全的,而push和empty方法调用了Vector的方法,由于Vector中的addElement()和size()方法都是线程安全的,所以Stack的每个方法也都是线程安全的,所以它和Vector一样,都是线程安全的。

总结

Vector与ArrayList的最大区别就是Vector是线程安全的,而ArrayList不是线程安全的。另外区别还有: 
- ArrayList不可以设置扩展的容量,默认1.5倍;Vector可以设置扩展的容量,如果没有设置,默认2倍 
- ArrayList的无参构造方法中初始容量为0,而Vector的无参构造方法中初始容量为10。 

- Vector线程安全,ArrayList线程不安全。

Vector和它的子类Stack都是线程安全的集合。


转载自:https://blog.csdn.net/qq_19431333/article/details/54908404

                http://www.cnblogs.com/skywang12345/p/3308833.html

猜你喜欢

转载自blog.csdn.net/qq_34645958/article/details/81057983