迭代器
在软构实验一的实现中,我初次接触到了迭代器,感觉这是一种非常新的遍历方式,于是又在网上查阅了不少资料,更加充分的了解了迭代器
可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
可以使用isinstance()判断一个对象是否是Iterable对象
j而ava Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,用来迭代hashset,arreyset等类型的集合。
Iterator 是 Java 迭代器最简单的实现,ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口。

迭代器 it 的两个基本操作是 next 、hasNext 和 remove。
调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。
调用 it.hasNext() 用于检测集合中是否还有元素。
调用 it.remove() 将迭代器返回的元素删除。
下面插入一段迭代器迭代的示例
1 // 引入 ArrayList 和 Iterator 类 2 import java.util.ArrayList; 3 import java.util.Iterator; 4 5 public class RunoobTest { 6 public static void main(String[] args) { 7 8 // 创建集合 9 ArrayList<String> sites = new ArrayList<String>(); 10 sites.add("Google"); 11 sites.add("Runoob"); 12 sites.add("Taobao"); 13 sites.add("Zhihu"); 14 15 // 获取迭代器 16 Iterator<String> it = sites.iterator(); 17 18 // 输出集合中的所有元素 19 while(it.hasNext()) { 20 System.out.println(it.next()); 21 } 22 } 23 }
可以看到迭代器可以很方便的对各种集合类进行迭代,而且操作都大体相同
在使用Iterator的时候禁止对所遍历的容器进行改变其大小结构的操作。例如: 在使用Iterator进行迭代时,如果对集合进行了add、remove操作就会出现ConcurrentModificationException异常。然而使用lterator.remove()却没有任何问题,其中原因就在于迭代器的实现上
1 private class Itr implements Iterator<E> { 2 int cursor; // index of next element to return 3 int lastRet = -1; // index of last element returned; -1 if no such 4 int expectedModCount = modCount; 5 6 public boolean hasNext() { 7 return cursor != size; 8 } 9 10 @SuppressWarnings("unchecked") 11 public E next() { 12 checkForComodification(); 13 int i = cursor; 14 if (i >= size) 15 throw new NoSuchElementException(); 16 Object[] elementData = ArrayList.this.elementData; 17 if (i >= elementData.length) 18 throw new ConcurrentModificationException(); 19 cursor = i + 1; 20 return (E) elementData[lastRet = i]; 21 } 22 23 public void remove() { 24 if (lastRet < 0) 25 throw new IllegalStateException(); 26 checkForComodification(); 27 28 try { 29 ArrayList.this.remove(lastRet); 30 cursor = lastRet; 31 lastRet = -1; 32 expectedModCount = modCount; 33 } catch (IndexOutOfBoundsException ex) { 34 throw new ConcurrentModificationException(); 35 } 36 } 37 38 final void checkForComodification() { 39 if (modCount != expectedModCount) 40 throw new ConcurrentModificationException(); 41 } 42 }
通过查看源码发现原来检查并抛出异常的是checkForComodification()方法。在ArrayList中modCount是当前集合的版本号,每次修改(增、删)集合都会加1;expectedModCount是当前迭代器的版本号,在迭代器实例化时初始化为modCount。
我们看到在checkForComodification()方法中就是在验证modCount的值和expectedModCount的值是否相等,所以当调用了ArrayList.add()或者ArrayList.remove()时,只更新了modCount的状态,而迭代器中的expectedModCount未同步,因此才会导致再次调用Iterator.next()方法时抛出异常。但是为什么使用Iterator.remove()就没有问题呢?通过源码的第32行发现,在Iterator的remove()中同步了expectedModCount的值,所以当你下次再调用next()的时候,检查不会抛出异常。

浙公网安备 33010602011771号