【源码】Vector、Stack源码解析
2014-08-11 16:09
260 查看
注:以下源码基于jdk1.7.0_11
Vector算是一个历史遗留下来的类,现在已基本被ArrayList取代。本文出于学习的目的来分析下这个类。
从图上可以看出Vector和ArrayList同样都直接继承于AbstractList,说明这两者功能上还是很相像的,事实也正是如此。
下面我们依然通过源码的方式解读Vector这个类。
protected Object[] elementData;//使用数组存储元素
protected int elementCount;//元素个数
protected int capacityIncrement;//扩容增量
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -2767605614048989439L;
Vector多了一个capacityIncrement这个变量,并且需要在构造器中指定这个值(默认为0,可以手动指定):
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() {//默认大小为10
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的初始容量与ArrayList一样,都是10。
下面来看下Vector的扩容机制:
但从方法命名上来看,跟ArrayList还是很类似的,但是两者的grow方法有点小区别:
Vector的扩容是基于capacityIncrement的,也就是所谓的扩容增量,如果该值不为0,那么每次扩容后的大小就是在原始容量加上扩容增量。如果未设置capacityIncrement,那么直接扩容为原来的两倍。
当然,前提是扩容后大小得大于等于所需要的最小容量minCapacity且不能超过MAX_ARRAY_SIZE,同时还要防止溢出(会抛出异常)。顺便复习下ArrayList的扩容机制:ArrayList每次扩容后大小都为原来的1.5倍。
接下来,我们观察一些方法:
可以发现,这些方法都加上了synchronized关键字,也就是说Vector是一个线程安全的类。
另外,Vector也是支持null元素的。
这个方法通过匿名内部类的方式构造一个Enumeration对象,并实现了hasMoreElements和nextElement方法,类似迭代器的hasNext和next方法。
以上就是Vector的内容,下面再看看Stack类:
总结:
1.Vector是线程安全的类而ArrayList不是;
2.Vector的扩容基于扩容增量,若扩容增量不为0,每次扩容的大小都为原始容量加上扩容增量,若扩容增量为0,也就是默认的情况下,扩容大小为元素容量的两倍;
3.Vector默认大小为10;
4.Vector支持null(ArrayList也可以);
5.Vector除了可以使用listIterator和Iterator遍历集合,也可以使用Enumeration的方式遍历;
6.Stack类继承了Vector,并封装了栈的操作。同时也是一个线程安全的类。
7.从性能上看,推荐使用ArrayList和LinkedList而不要使用Vector和Stack。
Vector算是一个历史遗留下来的类,现在已基本被ArrayList取代。本文出于学习的目的来分析下这个类。
从图上可以看出Vector和ArrayList同样都直接继承于AbstractList,说明这两者功能上还是很相像的,事实也正是如此。
下面我们依然通过源码的方式解读Vector这个类。
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.SerializableVector的继承关系和ArrayList保持一致。但是成员变量确不太一样:
protected Object[] elementData;//使用数组存储元素
protected int elementCount;//元素个数
protected int capacityIncrement;//扩容增量
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -2767605614048989439L;
Vector多了一个capacityIncrement这个变量,并且需要在构造器中指定这个值(默认为0,可以手动指定):
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() {//默认大小为10
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的初始容量与ArrayList一样,都是10。
下面来看下Vector的扩容机制:
public synchronized void ensureCapacity(int minCapacity) { if (minCapacity > 0) { modCount++; ensureCapacityHelper(minCapacity); } } private void ensureCapacityHelper(int minCapacity) { if (minCapacity - elementData.length > 0) grow(minCapacity); } private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 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); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
但从方法命名上来看,跟ArrayList还是很类似的,但是两者的grow方法有点小区别:
Vector的扩容是基于capacityIncrement的,也就是所谓的扩容增量,如果该值不为0,那么每次扩容后的大小就是在原始容量加上扩容增量。如果未设置capacityIncrement,那么直接扩容为原来的两倍。
当然,前提是扩容后大小得大于等于所需要的最小容量minCapacity且不能超过MAX_ARRAY_SIZE,同时还要防止溢出(会抛出异常)。顺便复习下ArrayList的扩容机制:ArrayList每次扩容后大小都为原来的1.5倍。
接下来,我们观察一些方法:
public synchronized void trimToSize() { modCount++; int oldCapacity = elementData.length; if (elementCount < oldCapacity) { elementData = Arrays.copyOf(elementData, elementCount); } } public synchronized int size() { return elementCount; } public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } public synchronized boolean removeElement(Object obj) { modCount++; int i = indexOf(obj); if (i >= 0) { removeElementAt(i); return true; } return false; }
可以发现,这些方法都加上了synchronized关键字,也就是说Vector是一个线程安全的类。
另外,Vector也是支持null元素的。
public synchronized int indexOf(Object o, int index) { if (o == null) { for (int i = index ; i < elementCount ; i++) if (elementData[i]==null) return i; } else { for (int i = index ; i < elementCount ; i++) if (o.equals(elementData[i])) return i; } return -1; }Vector除了ListIterator和iterator两种迭代方式之外,还有独特的迭代方式,那就是elements方法:
public Enumeration<E> elements() { return new Enumeration<E>() {//匿名内部类方式构造一个Enumeration对象。 int count = 0; public boolean hasMoreElements() { return count < elementCount; } public E nextElement() { synchronized (Vector.this) { if (count < elementCount) { return elementData(count++); } } throw new NoSuchElementException("Vector Enumeration"); } }; }
这个方法通过匿名内部类的方式构造一个Enumeration对象,并实现了hasMoreElements和nextElement方法,类似迭代器的hasNext和next方法。
以上就是Vector的内容,下面再看看Stack类:
public class Stack<E> extends Vector<E> { public Stack() { } 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; } /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = 1224463164541339165L; }
总结:
1.Vector是线程安全的类而ArrayList不是;
2.Vector的扩容基于扩容增量,若扩容增量不为0,每次扩容的大小都为原始容量加上扩容增量,若扩容增量为0,也就是默认的情况下,扩容大小为元素容量的两倍;
3.Vector默认大小为10;
4.Vector支持null(ArrayList也可以);
5.Vector除了可以使用listIterator和Iterator遍历集合,也可以使用Enumeration的方式遍历;
6.Stack类继承了Vector,并封装了栈的操作。同时也是一个线程安全的类。
7.从性能上看,推荐使用ArrayList和LinkedList而不要使用Vector和Stack。
相关文章推荐
- 给jdk写注释系列之jdk1.6容器(10)-Stack&Vector源码解析
- Vector、Stack源码解析
- Stack&Vector源码解析
- 给jdk写注释系列之jdk1.6容器(10)-Stack&Vector源码解析
- STL源码解析-04序列容器-04queue&stack
- [STL]源码解析:stack
- STL_学习_vector容器源码解析
- 开始我的第一篇文章 vector容器的源码解析
- STL源码结构解析之Stack,Queue,Priority_Queue
- Java 集合系列07之 Stack详细介绍(源码解析)和使用示例
- Java 集合系列06之 Vector详细介绍(源码解析)和使用示例
- Java 集合系列06之 Vector详细介绍(源码解析)和使用示例
- Java 集合系列06之 Vector详细介绍(源码解析)和使用示例
- STL源码解析—vector
- Java 集合系列 05 Vector详细介绍(源码解析)和使用示例
- List接口实现类-ArrayList、Vector、LinkedList集合深入学习以及源码解析
- [STL]源码解析:std::vector
- C++STL源码解析(一) ——vector
- Java 集合系列 06 Stack详细介绍(源码解析)和使用示例
- Java 集合系列06之 Vector详细介绍(源码解析)和使用示例