欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java Iterator接口实现代码解析

程序员文章站 2022-05-25 22:08:33
iterator接口源代码package java.util;import java.util.function.consumer;/** * an iterator over a collectio...

iterator接口

源代码

package java.util;

import java.util.function.consumer;

/**
 * an iterator over a collection. {@code iterator} takes the place of
 * {@link enumeration} in the java collections framework. iterators
 * differ from enumerations in two ways:
 *
 * <ul>
 *   <li> iterators allow the caller to remove elements from the
 *      underlying collection during the iteration with well-defined
 *      semantics.
 *   <li> method names have been improved.
 * </ul>
 *
 * <p>this interface is a member of the
 * <a href="{@docroot}/../technotes/guides/collections/index.html" rel="external nofollow" >
 * java collections framework</a>.
 *
 * @param <e> the type of elements returned by this iterator
 *
 * @author josh bloch
 * @see collection
 * @see listiterator
 * @see iterable
 * @since 1.2
 */
public interface iterator<e> {
  /**
   * returns {@code true} if the iteration has more elements.
   * (in other words, returns {@code true} if {@link #next} would
   * return an element rather than throwing an exception.)
   *
   * @return {@code true} if the iteration has more elements
   */
  boolean hasnext();

  /**
   * returns the next element in the iteration.
   *
   * @return the next element in the iteration
   * @throws nosuchelementexception if the iteration has no more elements
   */
  e next();

  /**
   * removes from the underlying collection the last element returned
   * by this iterator (optional operation). this method can be called
   * only once per call to {@link #next}. the behavior of an iterator
   * is unspecified if the underlying collection is modified while the
   * iteration is in progress in any way other than by calling this
   * method.
   *
   * @implspec
   * the default implementation throws an instance of
   * {@link unsupportedoperationexception} and performs no other action.
   *
   * @throws unsupportedoperationexception if the {@code remove}
   *     operation is not supported by this iterator
   *
   * @throws illegalstateexception if the {@code next} method has not
   *     yet been called, or the {@code remove} method has already
   *     been called after the last call to the {@code next}
   *     method
   */
  default void remove() {
    throw new unsupportedoperationexception("remove");
  }

  /**
   * performs the given action for each remaining element until all elements
   * have been processed or the action throws an exception. actions are
   * performed in the order of iteration, if that order is specified.
   * exceptions thrown by the action are relayed to the caller.
   *
   * @implspec
   * <p>the default implementation behaves as if:
   * <pre>{@code
   *   while (hasnext())
   *     action.accept(next());
   * }</pre>
   *
   * @param action the action to be performed for each element
   * @throws nullpointerexception if the specified action is null
   * @since 1.8
   */
  default void foreachremaining(consumer<? super e> action) {
    objects.requirenonnull(action);
    while (hasnext())
      action.accept(next());
  }
}

阅读笔记

1. iterator接口与enumeration接口的关系/iterator接口在java集合库中的作用

iterator接口是java集合框架的一部分,被用于替代原有的enumeration接口。(“iterator”比“enumeration”更简短、表意更清晰、功能更多,具体的信息下面enumeration接口的注解中说的挺清楚,且enumeration注解中也建议编程人员改用iterator接口)

java类库中,集合类的基本接口是collection接口,而collection接口实现了iterable接口,iterable接口中有一个iterator()方法用于获取iterator对象。

package java.util;

/**
 * an object that implements the enumeration interface generates a
 * series of elements, one at a time. successive calls to the
 * <code>nextelement</code> method return successive elements of the
 * series.
 * <p>
 * for example, to print all elements of a <tt>vector&lt;e&gt;</tt> <i>v</i>:
 * <pre>
 *  for (enumeration&lt;e&gt; e = v.elements(); e.hasmoreelements();)
 *    system.out.println(e.nextelement());</pre>
 * <p>
 * methods are provided to enumerate through the elements of a
 * vector, the keys of a hashtable, and the values in a hashtable.
 * enumerations are also used to specify the input streams to a
 * <code>sequenceinputstream</code>.
 * <p>
 * note: the functionality of this interface is duplicated by the iterator
 * interface. in addition, iterator adds an optional remove operation, and
 * has shorter method names. new implementations should consider using
 * iterator in preference to enumeration.
 *
 * @see   java.util.iterator
 * @see   java.io.sequenceinputstream
 * @see   java.util.enumeration#nextelement()
 * @see   java.util.hashtable
 * @see   java.util.hashtable#elements()
 * @see   java.util.hashtable#keys()
 * @see   java.util.vector
 * @see   java.util.vector#elements()
 *
 * @author lee boynton
 * @since  jdk1.0
 */
public interface enumeration<e> {
  /**
   * tests if this enumeration contains more elements.
   *
   * @return <code>true</code> if and only if this enumeration object
   *      contains at least one more element to provide;
   *     <code>false</code> otherwise.
   */
  boolean hasmoreelements();

  /**
   * returns the next element of this enumeration if this enumeration
   * object has at least one more element to provide.
   *
   * @return   the next element of this enumeration.
   * @exception nosuchelementexception if no more elements exist.
   */
  e nextelement();
}

2.hasnext()、next()、remove()方法的关系

hasnext()方法:判断是否还有元素可以进行迭代;

next()方法:迭代元素;

remove()方法:

/**
* remove from the underlying collection the last element returned by this iterator
*(optional operation). 
* 移除当前迭代器上一次从基础集合中迭代的元素(可选操作)
*
* this method can be called only once per call to next().
* 调用remove()方法前必须先调用next()方法,调用完一次remove()方法后想要再次调用remove()方法,
* 必须先调用next()方法。
*
* the behavior of an iterator is unspecified if the underlying collection is modifyed while
* the iteration is in progress is any way other than by call this method.
* 如果在迭代进行过程中修改了基础集合,则迭代器的行为是不确定的。
*/
public static void main(string[] args) {
    collection<string> stringcollection = new arraylist<>();
    stringcollection.add("hello");
    stringcollection.add("world");
    stringcollection.add("!");
    iterator<string> stringiterator = stringcollection.iterator();

    stringiterator.next();
    stringiterator.remove();//ok
  }
public static void main(string[] args) {
    ......
    stringiterator.next();
    stringcollection.add("abc");//基本集合被改变
    stringiterator.remove();//error - java.util.concurrentmodificationexception
  }
public static void main(string[] args) {
    ......
    stringiterator.next();
    stringcollection.add("abc");//基本集合被改变
    stringiterator.next();//error - java.util.concurrentmodificationexception
  }
public static void main(string[] args) {
    ......
    stringiterator.next();
    stringcollection.add("abc");//基本集合改变
    stringiterator = stringcollection.iterator();//重新获取迭代器
    stringiterator.next();//ok
    stringiterator.remove();//ok
  }

三者关系:调用remove()方法前必须先调用next()方法,调用next()方法前最好先调用hasnext()方法。

3.具体实现类

abstractlist类中定义了一个实现了iterator接口的内部类:

private class itr implements iterator<e> {
  /**
   * index of element to be returned by subsequent call to next.
   */
  int cursor = 0;

  /**
   * index of element returned by most recent call to next or
   * previous. reset to -1 if this element is deleted by a call
   * to remove.
   */
  int lastret = -1;

  /**
   * the modcount value that the iterator believes that the backing
   * list should have. if this expectation is violated, the iterator
   * has detected concurrent modification.
   */
  int expectedmodcount = modcount;

  public boolean hasnext() {
    return cursor != size();
  }

  public e next() {
    checkforcomodification();
    try {
      int i = cursor;
      e next = get(i);
      lastret = i;//最近一次调用next()方法返回的元素的下标。
      cursor = i + 1;//下一次调用next()方法返回的元素的下标。
      return next;
    } catch (indexoutofboundsexception e) {
      checkforcomodification();
      throw new nosuchelementexception();
    }
  }

  public void remove() {
    if (lastret < 0)
      throw new illegalstateexception();//所以,调用remove()前必须先调用next()
    checkforcomodification();

    try {
      abstractlist.this.remove(lastret);
      if (lastret < cursor)
        cursor--;//因为移除了一个元素
      lastret = -1;//所以,不能连续调用两次remove()方法
      expectedmodcount = modcount;
    } catch (indexoutofboundsexception e) {
      throw new concurrentmodificationexception();
    }
  }

  final void checkforcomodification() {
    if (modcount != expectedmodcount)
      throw new concurrentmodificationexception();
  }
}

看完上面的代码,我对modcount、expectedmodcount变量以及checkforcomodification()方法的作用比较好奇,所以尝试着去搞清楚。

先来看modecount变量,这个变量被声明在内部类的外部:

public abstract class abstractlist<e> extends abstractcollection<e> implements list<e> {
  /**
   * the number of times this list has been <i>structurally modified</i>.
   * structural modifications are those that change the size of the
   * list, or otherwise perturb it in such a fashion that iterations in
   * progress may yield incorrect results.
   * 用于表示该列表发生结构性修改的次数。结构性修改是指*更改列表的大小*或*以其他
   * 方式干扰列表*,即正在进行的迭代可能会产生错误的结果。
   *
   * <p>this field is used by the iterator and list iterator implementation
   * returned by the {@code iterator} and {@code listiterator} methods.
   * if the value of this field changes unexpectedly, the iterator (or list
   * iterator) will throw a {@code concurrentmodificationexception} in
   * response to the {@code next}, {@code remove}, {@code previous},
   * {@code set} or {@code add} operations. this provides
   * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
   * the face of concurrent modification during iteration.
   * 设计者认为,与其因为基本集合被并发修改从而使迭代产生不确定行为,不如尽早给出错误。
   *
   * <p><b>use of this field by subclasses is optional.</b> if a subclass
   * wishes to provide fail-fast iterators (and list iterators), then it
   * merely has to increment this field in its {@code add(int, e)} and
   * {@code remove(int)} methods (and any other methods that it overrides
   * that result in structural modifications to the list). a single call to
   * {@code add(int, e)} or {@code remove(int)} must add no more than
   * one to this field, or the iterators (and list iterators) will throw
   * bogus {@code concurrentmodificationexceptions}. if an implementation
   * does not wish to provide fail-fast iterators, this field may be
   * ignored.
   * 是否使用应需求决定。
   */
  protected transient int modcount = 0;
}

看完上面的源码注解,已经大概能够知道modcount、expectedmodcount以及checkforcomodification()的作用了。

假如把基础集合当作一个银行账号,基础集合中的元素表示存款。那么modcount就相当于银行为每个账号做的消费记录,expectedmodcount就相当于是账号持有人自己做的一份消费记录,一般银行和账号持有人自己做的消费记录都不会出错。

final void checkforcomodification() {
  if (modcount != expectedmodcount)
    throw new concurrentmodificationexception();
}

一旦银行那边的消费记录和自己手里的那份消费记录对不上,肯定是账号被盗用了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。