本帖最后由 大蓝鲸Java 于 2017-11-29 00:08 编辑
【南京校区】毁人不倦篇之二 --- 迭代器完全解析 在我们平时Java的学习过程中,有一些常识性问题,我们都默守陈规的遵守了这些的原则,殊不知我们的Java是一个极具自由的语言,正如我们程序员的一样,放荡不羁爱自由。 在我们平时写一些代码的时候,如果多思考一下,往往会有一些出乎意料的答案产生。 比如:毁人不倦篇之二 --- 迭代器完全解析 首先API中,以及现在网络上各种对迭代器的解析并不全面,且解释有误。这是被API给坑了。 API中关于迭代器中next方法解释如下: next(); 返回迭代的下一个元素 这里不禁有很多人会认为迭代器刚开始的时候指向的是集合中的-1索引处 但是实际上真的是这样吗? 我们翻看源码 int cursor; 是做为一个成员变量了,int类型的成员变量初始化值为0.所以显然并不是如API中所说。 关于迭代器的具体分析会在下文详细解释。 首先,迭代器是设计模式中的一种。 迭代器设计模式:
提供一种方法访问容器中的各个元素,而又不暴露该对象的内部细节。 使用场景: 和容器经常在一起,我们定义了一个容器,还要提供外部访问的方法,迭代器模式无疑是最好不过了。 [AppleScript] 纯文本查看 复制代码 private class Itr implements Iterator<E> {[/align] int cursor; //游标,可理解为指针。初始化默认值是0.
int lastRet = -1; //一个控制不能连续remove的变量
int expectedModCount = modCount;//并发修改异常的控制条件
public boolean hasNext() { //判断是否有元素可迭代
return cursor != size; //实际就是判断当前游标指向的那个索引是否有元素
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();//并发修改异常的判断
int i = cursor;//将游标赋值给一个局部变量i
if (i >= size)//如果超出集合的最大索引
throw new NoSuchElementException();//报没有元素异常
Object[] elementData = ArrayList.this.elementData;//将集合拷贝一个副本
if (i >= elementData.length)//此时i的值记录的是游标的值
throw new ConcurrentModificationException();//如果游标大于副本的长度,则同样报并发修改异常 //但是这个判断不会走到,因为副本的长度即集合的长度
//
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
|