文章首發(fā)csdn博客地址:https://blog.csdn.net/u013277209?viewmode=contents
一:Vector分析
Vector 是線程安全的動態(tài)數(shù)組串述,同 ArrayList 一樣繼承自 AbstractList 且實現(xiàn)了 List执解、RandomAccess、Cloneable纲酗、Serializable 接口衰腌。
內(nèi)部實現(xiàn)依然基于數(shù)組,Vector 與 ArrayList 基本是一致的觅赊,唯一不同的是 Vector 是線程安全的右蕊,會在可能出現(xiàn)線程安全的方法前面加上 synchronized 關(guān)鍵字。
其和 ArrayList 類似吮螺,隨機訪問速度快饶囚,插入和移除性能較差(數(shù)組原因),支持 null 元素鸠补,有順序萝风,元素可以重復(fù),線程安全紫岩。
變量以及初始化:
/**
* 存儲元素數(shù)組
*/
protected Object[] elementData;
/**
* 元素個數(shù)
*/
protected int elementCount;
/**
* 容量增長的系數(shù)
*/
protected int capacityIncrement;
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -2767605614048989439L;
/**
* 指定容量和增長系數(shù)的構(gòu)造函數(shù)
*/
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
/**
* 指定容量構(gòu)造函數(shù)
*/
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
/**
* 空構(gòu)造函數(shù)闹丐,默認容量10
*/
public Vector() {
this(10);
}
/**
* 包含指定集合的構(gòu)造函數(shù)
*/
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);
}
elementData前面并沒有transient關(guān)鍵字,但是他也實現(xiàn)了自定義序列化操作被因,前面我們了解過卿拴,如果類中自定義了readObject和writeObject,那么序列化時會調(diào)用這兩個函數(shù)梨与,如果類中不自定義readObject與writeObject堕花,那么類在序列化的時候會調(diào)用ObjectInputStream與ObjectOutputStream中的defaultReadObject與defaultWriteObject方法進行默認序列化。
下面我們看一下Vector中自定義的readObject和writeObject
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gfields = in.readFields();
int count = gfields.get("elementCount", 0);
Object[] data = (Object[])gfields.get("elementData", null);
if (count < 0 || data == null || count > data.length) {
throw new StreamCorruptedException("Inconsistent vector internals");
}
elementCount = count;
elementData = data.clone();
}
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
final java.io.ObjectOutputStream.PutField fields = s.putFields();
final Object[] data;
synchronized (this) {
fields.put("capacityIncrement", capacityIncrement);
fields.put("elementCount", elementCount);
data = elementData.clone();
}
fields.put("elementData", data);
s.writeFields();
}
擴容
Vector 在 capacityIncrement 大于 0 時擴容 capacityIncrement 大小粥鞋,否則擴容為原始容量的 2 倍缘挽,而ArrayList 在默認數(shù)組容量不夠時默認擴展是 1.5 倍。
public synchronized void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
modCount++;
ensureCapacityHelper(minCapacity);
}
}
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);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
增刪改查
Vector是JDK1.0時已經(jīng)有的呻粹,而List框架是1.2時才出現(xiàn)的壕曼,所以Vector在List接口定義的增刪改查以外還有他自己定義的增刪改查方法,我們來看一下:
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
public boolean remove(Object o) {
return removeElement(o);
}
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--elementCount] = null; // Let gc do its work
return oldValue;
}
public synchronized void removeElementAt(int index) {
modCount++;
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
public synchronized void setElementAt(E obj, int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
elementData[index] = obj;
}
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
return elementData(index);
}
增刪改查方法基本上一樣等浊,所以Vector里面包含了大量實現(xiàn)相同的方法腮郊。
迭代器實現(xiàn)
Vector中迭代器實現(xiàn)和ArrayList中一樣的,只不過Vector中為了保證線程安全筹燕,在方法體里面加了synchronized關(guān)鍵字轧飞。
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
// Racy but within spec, since modifications are checked
// within or after synchronization in next/previous
return cursor != elementCount;
}
public E next() {
synchronized (Vector.this) {
checkForComodification();
int i = cursor;
if (i >= elementCount)
throw new NoSuchElementException();
cursor = i + 1;
return elementData(lastRet = i);
}
}
public void remove() {
if (lastRet == -1)
throw new IllegalStateException();
synchronized (Vector.this) {
checkForComodification();
Vector.this.remove(lastRet);
expectedModCount = modCount;
}
cursor = lastRet;
lastRet = -1;
}
@Override
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
synchronized (Vector.this) {
final int size = elementCount;
int i = cursor;
if (i >= size) {
return;
}
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) Vector.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
action.accept(elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* An optimized version of AbstractList.ListItr
*/
final class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
public E previous() {
synchronized (Vector.this) {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
cursor = i;
return elementData(lastRet = i);
}
}
public void set(E e) {
if (lastRet == -1)
throw new IllegalStateException();
synchronized (Vector.this) {
checkForComodification();
Vector.this.set(lastRet, e);
}
}
public void add(E e) {
int i = cursor;
synchronized (Vector.this) {
checkForComodification();
Vector.this.add(i, e);
expectedModCount = modCount;
}
cursor = i + 1;
lastRet = -1;
}
}
克隆實現(xiàn)
Vector克隆實現(xiàn)和ArrayList的實現(xiàn)一致,都是通過數(shù)組元素拷貝來實現(xiàn)的淺拷貝
public synchronized Object clone() {
try {
@SuppressWarnings("unchecked")
Vector<E> v = (Vector<E>) super.clone();
v.elementData = Arrays.copyOf(elementData, elementCount);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
為什么現(xiàn)在都不提倡使用 Vector 了撒踪?
因為 Vector 實現(xiàn)并發(fā)安全的原理是在每個操作方法上加鎖过咬,這些鎖并不是必須要的,在實際開發(fā)中一般都是通過鎖一系列的操作來實現(xiàn)線程安全制妄,也就是說將需要同步的資源放一起加鎖來保證線程安全掸绞,如果多個 Thread 并發(fā)執(zhí)行一個已經(jīng)加鎖的方法,但是在該方法中又有 Vector 的存在耕捞,Vector 本身實現(xiàn)中已經(jīng)加鎖了衔掸,雙重鎖會造成額外的開銷,即 Vector 同 ArrayList 一樣有 fail-fast 問題(即無法保證遍歷安全)砸脊,所以在遍歷 Vector 操作時又得額外加鎖保證安全具篇,還不如直接用 ArrayList 加鎖性能好,所以在 JDK 1.5 之后推薦使用 java.util.concurrent 包下的并發(fā)類凌埂。此外 Vector 是一個從 JDK1.0 就有的古老集合驱显,那時候 Java 還沒有提供系統(tǒng)的集合框架,所以在 Vector 里提供了一些方法名很長的方法(如 addElement(Object obj)瞳抓,實際上這個方法和 add(Object obj) 沒什么區(qū)別)埃疫,從 JDK1.2 以后 Java 提供了集合框架,然后就將 Vector 改為實現(xiàn) List 接口孩哑,從而導(dǎo)致 Vector 里有一些重復(fù)的方法栓霜。
二、Stack分析
通過繼承Vector類横蜒,Stack類可以很容易的實現(xiàn)他本身的功能胳蛮。因為大部分的功能在Vector里面已經(jīng)提供支持了销凑。
在Java中Stack類表示后進先出(LIFO)的對象堆棧。棧是一種非常常見的數(shù)據(jù)結(jié)構(gòu)仅炊,它采用典型的先進后出的操作方式完成的斗幼。
Stack通過五個操作對Vector進行擴展,允許將向量視為堆棧抚垄。這個五個操作如下:
- empty() 測試堆棧是否為空蜕窿。
- peek() 查看堆棧頂部的對象,但不從堆棧中移除它呆馁。
- pop() 移除堆棧頂部的對象桐经,并作為此函數(shù)的值返回該對象。
- push(E item) 把項壓入堆棧頂部浙滤。
- search(Object o) 返回對象在堆棧中的位置阴挣,以 1 為基數(shù)。
我們看一下源碼:
public class Stack<E> extends Vector<E> {
/**
* Creates an empty Stack.
*/
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;
}
/**
* 返回棧頂元素节猿,不執(zhí)行刪除操作
*/
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
/**
* 棧是否為空
*/
public boolean empty() {
return size() == 0;
}
/**
* 查找“元素o”在棧中的位置:由棧底向棧頂方向數(shù)
*/
public synchronized int search(Object o) {
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
}