JDK的棄兒:Vector、Stack、Hashtable、Enumeration

隨着JDK的發展,一些設計缺陷或者性能不足的類庫不免會被淘汰,最多見的就是Vector、Stack、HashTable和Enumeration了。java

Vector(@since 1.0)

首先看看Vector的UML類圖,能夠看出,他是一個與ArrayList有着相同繼承體系的類,大體功能也和ArrayList同樣。Vector與ArrayList最大的不一樣點在於它是線程安全的,由於其內部幾乎全部方法都用了synchronized來修飾。可是,Synchronized是重量級鎖,讀寫操做也沒有作適當的併發優化,已經被併發性更好的CopyOnWriteArrayList取代了。因此,當不要求線程安全時,天然會選擇ArrayList,若是要求線程安全,每每也會選擇CopyOnWriteArrayList或者Collections.synchronizedList()。
算法

Stack(@since 1.0)

Stack是Vector的子類,其內部的方法也都是經過無腦加synchronized來實現的,因此雖然線程安全,可是併發性不高。當不要求線程安全時,會選擇LinkedList或者ArrayList(LinkedList的API更接近棧的操做,因此最佳選擇是LinkedList),當要求線程安全時,咱們會用java.util.concurrent包下的某些類。
再多句嘴,雖然LinkedList的API比較接近棧的操做,可是暴露了許多用不着的方法,這會帶來危險。解決方法是編寫一個LinkedList的包裝類,只暴露與棧相關的方法。安全

 1 **
 2  * 包裝{@code LinkedList},使其僅暴露與棧相關的方法
 3  */
 4 public class Stack<T> {
 5     private LinkedList<T> list;
 6     public Stack() {
 7         list = new LinkedList<>();
 8     }
 9     public void push(T item) {
10         list.push(item);
11     }
12     public T pop() {
13         return list.pop();
14     }
15     public T peek() {
16         return list.peek();
17     }
18     public boolean isEmpty() {
19         return list.isEmpty();
20     }
21     @Override
22     public String toString() {
23         return list.toString();
24     }
25 }

 

Hashtable(@since JDK1.0)

首先看看Hashtable的UML類圖,關鍵點是其實現了Map接口,因此它是一個存儲鍵值對的容器。經過查看源碼,咱們知道,其是一個線程安全的類,並且仍是用synchronized來實現的,因此併發性不高。因此,當面對不要求線程安全的應用場景時咱們會用HashMap代替,要求線程安全的應用場景咱們每每也會用ConcurrentHashMap或者Collections.synchronizedMap()來代替。
 
再再多句嘴,它與HashMap還有一個比較出名的不一樣點,就是它的散列表實現算法是用線性探測法實現的,該算法要求key不能爲null,否則刪除鍵值對時會出問題。另外還要求value不能爲null。具體見源碼。併發

 1 public synchronized V put(K key, V value) {
 2     // Make sure the value is not null
 3     if (value == null) { //value不能爲null
 4         throw new NullPointerException();
 5     }
 6     // Makes sure the key is not already in the hashtable.
 7     Entry<?,?> tab[] = table;
 8     int hash = key.hashCode(); //key不能夠爲null
 9     int index = (hash & 0x7FFFFFFF) % tab.length;
10     @SuppressWarnings("unchecked")
11     Entry<K,V> entry = (Entry<K,V>)tab[index];
12     for(; entry != null ; entry = entry.next) {
13         if ((entry.hash == hash) && entry.key.equals(key)) {
14             V old = entry.value;
15             entry.value = value;
16             return old;
17         }
18     }
19     addEntry(hash, key, value, index);
20     return null;
21 }
22 public synchronized boolean contains(Object value) {
23     if (value == null) {
24         throw new NullPointerException();//value不能爲null
25     }
26     Entry<?,?> tab[] = table;
27     for (int i = tab.length ; i-- > 0 ;) {
28         for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
29             if (e.value.equals(value)) {
30                 return true;
31             }
32         }
33     }
34     return false;
35 }

Enumeration(@since JDK1.0)

Enumeration是不是JDK的「棄兒」實際上是有爭論的,有人認爲,有了Iterator的存在,Enumeration存在的意義就僅僅是兼容老API(好比Vector、Hashtable)了;又有人認爲,Enumeration提供了比Iterator更明確的語義(明確不但願對象被執行移除操做)。ide

1     * NOTE: The functionality of this interface is duplicated by the Iterator
2     * interface.  In addition, Iterator adds an optional remove operation, and
3     * has shorter method names.  New implementations should consider using
4     * Iterator in preference to Enumeration.
5     這個接口的功能與Iterator接口重複了。此外,Iteraotr還有一個可選的remove()方法和更短的名字,新應用應該優先考慮Iterator。

總之,根據API的說明,咱們得知,新應用應優先考慮Iterator接口。
再再再多句嘴,萬一要面對Enumeration,又想有個關於迭代的統一接口,可使用適配器模式來處理Enumeration。工具

 1 ** 
 2  * 把Enumeration接口轉換成Iterator接口的適配器  
 3  * 適配器模式中的角色 - adaptor 
 4  */  
 5 public class EnumerationIterator<E> implements Iterator<E> {  
 6     /** 
 7      * 被適配的接口 
 8      * 適配器模式中的角色 - adaptee  
 9      */  
10     private Enumeration<E> enums;  
11     public EnumerationIterator(Enumeration<E> enums) {  
12         this.enums = enums;  
13     }  
14     @Override  
15     public boolean hasNext() {  
16         return enums.hasMoreElements();  
17     }  
18     @Override  
19     public E next() {  
20         return enums.nextElement();  
21     }  
22     /** 
23      * 由於Enumeration接口不支持remove操做,因此這裏簡單地拋出異常 
24      */  
25     @Override  
26     public void remove() {  
27         throw new UnsupportedOperationException();  
28     }  
29 }

總結

Vector、Stack、Hashtable因爲其自身的設計不足並且又有替代的工具,因此在新項目中已難尋其蹤。Iterator的強大功能也使Enumeration處境尷尬,也已經不多見到了。性能

引用

1.http://blog.csdn.net/tounaobun/article/details/8581429
2.https://www.zhihu.com/question/42961567?sort=created優化

相關文章
相關標籤/搜索