公子姓王

导航

Java容器解析系列(1) 迭代的进化——从Enumeration到Iterator

在Java中,对于所有的Collection,都有一个特性,可以通过迭代器来遍历和删除其中的元素,因为Collection接口继承自Iterable接口.

public interface Collection<E> extends Iterable<E> 

Iterable接口中只有一个方法:

    /**
     该接口的实现类可以被用于"foreach"语句
    * @since 1.5
    */
    public interface Iterable<T> {
    // 返回对象的迭代器
    Iterator<T> iterator();
    }

Iterable接口除了提供iterator()方法返回迭代器之外,所有实现了Iterable接口的类都可以通过foreach语句调用.
其实,foreach语句遍历Collection的本质就是对Iterable接口的调用.

关于foreach的具体原理,可以参考:
Java for-each 原理相关解析
java foreach原理

接下来看iterator()方法返回的Iterator接口,其为具体的迭代器实现提供了规范和指引:

/**  
 对指定Collection的迭代器,用于替换之前的迭代器接口Enumeration.
 Iterator与Enumeration的区别在于:
 1. Iterator允许在well-defined semantics的情况下删除Collection中的元素(这个是可选操作);
 2. 方法名更加精炼;
 well-defined semantics:生硬一点可以翻译为"语义良好的",这里为了不引起误解,使用原英文;
 @since 1.2 
*/
public interface Iterator<E> {

    // 如果还有更多元素,返回true,否则返回false;
    // 如果返回true,调用next()会返回下一个元素;
    boolean hasNext();

    // 返回迭代过程中的下一个元素,如果没有下一个元素,抛出NoSuchElementException;
    // hasNext()返回true是next()会返回下一个元素的保证;
    E next();

     // 移除Collection中上一次调用next()方法返回的对象,这是一个可选操作(optional operation);
     // 如果调用remove()之前没有调用next()方法,抛出UnsupportedOperationException;
     // 如果调用next()之后,调用了remove()方法,在下一次调用remove()方法之前,如果没有再次调用next()方法,则remove()方法抛出IllegalStateException;
     // 后面这两条应当视为well-defined semantics的一些规定了,除此之外remove()方法还可能涉及到fast-fail机制等;
     void remove();
}

Iterator包含的方法已经将其作为一个迭代器的本质表现得一丝不挂.而其诞生的目的是用于替换老旧的Enumeration接口.

本篇只讲Iterator接口的jdk设计,至于其使用,我们在讲述具体Collection时再陈述.因为每个具体的实现都不同,且其中还涉及到fast-fail机制等.

基于之前读过的很多资料还是有关于Enumeration的使用,让人心烦,所以还是看一下这个接口的具体内容.

/**
一个实现该Enumeration接口的对象能够遍历一系列元素.每次调用nextElement返回这个系列中的下一个元素;
这个类与Iterator的功能重复,新的迭代器推荐使用Iterator实现;
 * @since   JDK1.0
 */
public interface Enumeration<E> {

    // 如果还有更多元素,返回true,否则返回false;
    // 如果返回true,调用next()方法会返回下一个元素;
    // 这个方法对应Iterator的hasNext()方法;
    boolean hasMoreElements();

     // 返回迭代过程中的下一个元素,如果没有下一个元素,抛出NoSuchElementException;
     // hasMoreElements()返回true是nextElement方法会返回下一个元素的保证;
    // 该方法对应Iterator的next()方法;
    E nextElement();
}

Enumeration 接口自jdk1.0就添加进来了,常见的使用Enumeration的地方包括:

  1. 在Vector中用于遍历元素;
  2. 在Hashtable用于对keys和values的遍历;
  3. 在SequenceInputStream用于指定多个InputStream进行对象构造;

posted on 2018-10-12 16:39  公子姓王  阅读(263)  评论(0编辑  收藏  举报