Iterator与 Enumeration
"迭代器” (Iterator) ,它属于一种对象,负责选择集合内
的元素,并把它们提供给继承器的用户。作为一个类,它也提供了一级抽象。利
用这一级抽象,可将集合细节与用于访问那个集合的代码隔离开。通过继承器的
作用,集合被抽象成一个简单的序列。继承器允许我们遍历那个序列,同时毋需
关心基础结构是什么——换言之, 不管它是一个矢量、 一个链接列表、 一个堆栈,
还是其他什么东西。这样一来,我们就可以灵活地改变基础数据,不会对程序里
的代码造成干扰。Java 最开始(在 1.0 和 1.1 版中)提供的是一个标准继承器,
名为 Enumeration(枚举) ,为它的所有集合类提供服务。Java 1.2 新增一个更复
杂的集合库, 其中包含了一个名为Iterator的继承器, 可以做比老式的Enumeration
更多的事情。
1、Iterator和Enumeration的主要区别
Iterator也是一个接口,它的源码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package java.util; public abstract interface Iterator<E> { public abstract boolean hasNext(); public abstract E next(); public abstract void remove(); }
Enumeration是一个接口,它的源码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package java.util; public abstract interface Enumeration<E> { public abstract boolean hasMoreElements(); public abstract E nextElement(); }
(1)java中的集合类都提供了返回Iterator的方法,就是迭代器,它和Enumeration(枚举)的主要区别其实就是Iterator可以删除元素,但是Enumration却不能。
(2)还有一点要注意的就是,使用Iterator来遍历集合时,应使用Iterator的remove()方法来删除集合中的元素,使用集合的remove()方法将抛出ConcurrentModificationException异常。
(3)Enumeration 接口的功能与 Iterator 接口的功能是重复的。此外,Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。新的实现应该优先考虑使用 Iterator 接口而不是 Enumeration 接口。
(4)迭代器与枚举有两点不同:
·迭代器允许调用者利用定义良好的语义在迭代期间从迭代器所指向的 collection 移除元素。
·方法名称得到了改进。
2、Iterator中的hasnext(),next(),remove()三个方法在哪个类中实现的
通过查看rt.jar 中的源码以及查看jdk-api文档,发现好多类都是用内部类实现这个接口 然后用方法把该类返回给你使用
这就是遍历器模式 如LinkedList、ArrayList等。
ArrayList 内部实现如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public Iterator<E> iterator() { return new Itr(null); } private class Itr implements Iterator<E> { int cursor; int lastRet = -1; int expectedModCount = ArrayList.this.modCount; private Itr() { } public boolean hasNext() { return this.cursor != ArrayList.this.size; } public E next() { checkForComodification(); int i = this.cursor; if (i >= ArrayList.this.size) throw new NoSuchElementException(); Object[] arrayOfObject = ArrayList.this.elementData; if (i >= arrayOfObject.length) throw new ConcurrentModificationException(); this.cursor = (i + 1); return arrayOfObject[(this.lastRet = i)]; } public void remove() { if (this.lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(this.lastRet); this.cursor = this.lastRet; this.lastRet = -1; this.expectedModCount = ArrayList.this.modCount; } catch (IndexOutOfBoundsException localIndexOutOfBoundsException) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (ArrayList.this.modCount != this.expectedModCount) throw new ConcurrentModificationException(); } }
3、我们编写一个Hashtable,然后分别通过 Iterator 和 Enumeration 去遍历它,比较它们的效率
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Map.Entry; import java.util.Random; /* * 测试分别通过 Iterator 和 Enumeration 去遍历Hashtable * @author skywang */ public class IteratorEnumeration { public static void main(String[] args) { int val; Random r = new Random(); Hashtable table = new Hashtable(); for (int i=0; i<100000; i++) { // 随机获取一个[0,100)之间的数字 val = r.nextInt(100); table.put(String.valueOf(i), val); } // 通过Iterator遍历Hashtable iterateHashtable(table) ; // 通过Enumeration遍历Hashtable enumHashtable(table); } /* * 通过Iterator遍历Hashtable */ private static void iterateHashtable(Hashtable table) { long startTime = System.currentTimeMillis(); Iterator iter = table.entrySet().iterator(); while(iter.hasNext()) { //System.out.println("iter:"+iter.next()); iter.next(); } long endTime = System.currentTimeMillis(); countTime(startTime, endTime); } /* * 通过Enumeration遍历Hashtable */ private static void enumHashtable(Hashtable table) { long startTime = System.currentTimeMillis(); Enumeration enu = table.elements(); while(enu.hasMoreElements()) { //System.out.println("enu:"+enu.nextElement()); enu.nextElement(); } long endTime = System.currentTimeMillis(); countTime(startTime, endTime); } private static void countTime(long start, long end) { System.out.println("time: "+(end-start)+"ms"); } }
运行结果如下:
time: 9ms
time: 5ms
从中,我们可以看出。Enumeration 比 Iterator 的遍历速度更快。为什么呢?
这是因为,Iterator添加了对fail-fast机制的支持;所以,执行的效率慢一些。
Fail-Fast机制:请参考下一篇日记"fail-fast机制"