Java Iterator接口实现代码解析
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<e></tt> <i>v</i>: * <pre> * for (enumeration<e> 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(); }
一旦银行那边的消费记录和自己手里的那份消费记录对不上,肯定是账号被盗用了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 全网最详细的vscode基础教程
推荐阅读
-
通过spring用beanshell实现java接口示例
-
java身份证验证代码实现
-
java得到某年某周的第一天实现思路及代码
-
java整数与byte数组的转换实现代码
-
java实现memcache服务器的示例代码
-
android客户端从服务器端获取json数据并解析的实现代码
-
php与java通过socket通信的实现代码
-
android BottomSheetDialog新控件解析实现知乎评论列表效果(实例代码)
-
Java8如何将Array转换为Stream的实现代码
-
Mybaits 源码解析 (五)----- 面试源码系列:Mapper接口底层原理(为什么Mapper不用写实现类就能访问到数据库?)