Iterator,ListIterator与Enumeration接口
- Iterator接口与ListIterator接口都是迭代器接口,Enumeration接口是枚举接口。
- 三个接口均位于java.util包下。
- 三个接口均属于设计模式,即提供了一个方法,能够对集合或容器内的元素进行遍历,而不用关注底层实现细节,达到了数据与上层遍历解耦的目的。
先看下三个接口的源码:
Iterator接口源码:
package java.util;
public interface Iterator<E> {
boolean hasNext();//判断集合中是否还有元素可以迭代
E next();//返回迭代的下一个元素
void remove();//从迭代器指向的集合中移除迭代器返回的最后一个元素(可选操作)
}
ListIterator接口源码:
package java.util;
public interface ListIterator<E> extends Iterator<E> {//继承了Iterator接口
boolean hasNext();//以正向遍历列表时,判断集合中是否还有元素可以迭代
E next();//以正向遍历列表时,返回迭代的下一个元素
boolean hasPrevious();//以反向遍历列表时,判断集合中是否还有元素可以迭代
E previous();//以反向遍历列表时,返回列表中的前一个元素。
int nextIndex();//返回对 next 的后续调用所返回元素的索引。(如果列表迭代器在列表的结尾,则返回列表的大小)。
int previousIndex();//返回对 previous 的后续调用所返回元素的索引。(如果列表迭代器在列表的开始,则返回 -1)。
void remove();//从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
void set(E e);//用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
void add(E e);//将指定的元素插入列表(可选操作)。
}
Enumeration接口源码:
package java.util;
public interface Enumeration<E> {
boolean hasMoreElements();//测试此枚举是否包含更多的元素。
E nextElement();//如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。
}
从三个接口的源码来看,我们可以回答以下问题:
Iterator接口与ListIterator接口有什么异同点?
相同点:
都是迭代器,当需要对集合中元素进行遍历而不需要干涉其遍历过程时,这两种迭代器都可以使用。
不同点:
适用范围不同:Iterator可以应用于Set,List,Map和这些集合的子类型,而ListIterator只能用于List及其子类型。
涵盖方法不同:ListIterator继承了Iterator,除了实现了Iterator里的方法之外,还实现了其他方法。
遍历方式不同:Iterator只能顺序向后遍历,ListIterator可以实现双向遍历。
Iterator接口与Enumeration接口有什么异同点?
相同点
两个接口都可以实现遍历功能。
不同点
实现功能范围不同:Enumeration仅能实现遍历功能,Iterator不但能实现遍历功能,还能实现删除元素的功能。
方法名记忆难易程度不同:Iterator实现的方法的名字更短更好记。
一般情况下,均使用Iterator而不用Enumeration。
值得注意的是:
1.迭代器操作的数据均是集合本身的数据。
2.使用迭代器遍历时可能出现并发异常问题,即抛出java.util.ConcurrentModificationException异常。
这是因为调用实例对象的删除方法导致modCount和expectedModCount的值不一致。在单线程下换成迭代器对象的删除方法即可解决。
3.对迭代器而言,有快速失败和安全失败两种机制。
fair-fast快速失败机制:当在迭代一个集合的时候,如果有另外一个线程在修改这个集合,就会抛出ConcurrentModification异常,java.util下都是快速失败。
fair-safe安全失败机制:在迭代时会在集合二层做一个拷贝,修改集合上层元素不会影响下层。在java.util.concurrent下都是安全失败。