随着JDK的发展,一些设计缺陷或者性能不足的类库不免会被淘汰,最多见的就是Vector、Stack、HashTable和Enumeration了。java
首先看看Vector的UML类图,能够看出,他是一个与ArrayList有着相同继承体系的类,大体功能也和ArrayList同样。Vector与ArrayList最大的不一样点在于它是线程安全的,由于其内部几乎全部方法都用了synchronized来修饰。可是,Synchronized是重量级锁,读写操做也没有作适当的并发优化,已经被并发性更好的CopyOnWriteArrayList取代了。因此,当不要求线程安全时,天然会选择ArrayList,若是要求线程安全,每每也会选择CopyOnWriteArrayList或者Collections.synchronizedList()。 算法
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的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是不是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优化