Iterator接口
源代码
package java.util; import java.util.function.Consumer; public interface Iterator{ boolean hasNext(); E next(); default void remove() { throw new UnsupportedOperationException("remove"); } 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; public interface Enumeration{ boolean hasMoreElements(); E nextElement(); }
2.hasNext()、next()、remove()方法的关系
hasNext()方法:判断是否还有元素可以进行迭代;
next()方法:迭代元素;
remove()方法:
public static void main(String[] args) {
Collection stringCollection = new ArrayList<>();
stringCollection.add("Hello");
stringCollection.add("World");
stringCollection.add("!");
Iterator 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{ int cursor = 0; int lastRet = -1; 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 AbstractListextends AbstractCollection implements List { protected transient int modCount = 0; }
看完上面的源码注解,已经大概能够知道modCount、expectedModCount以及checkForComodification()的作用了。
假如把基础集合当作一个银行账号,基础集合中的元素表示存款。那么modCount就相当于银行为每个账号做的消费记录,expectedModCount就相当于是账号持有人自己做的一份消费记录,一般银行和账号持有人自己做的消费记录都不会出错。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
一旦银行那边的消费记录和自己手里的那份消费记录对不上,肯定是账号被盗用了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。



