`
francis.xjl
  • 浏览: 16122 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

关于Iterator

JDK 
阅读更多
JDK是这么说的:
在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器自身的remove 或 add 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒在将来不确定的时间任意发生不确定行为的风险。

注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。

那么

迭代器Iterator如何知道是否是自身进行结构上的修改?是因为这些集合内部有一个modCount参数,每一次的remove或add都会使modCount累加,而对应的迭代器内部则有一个expectedModCount参数,在创建Iterator时将modeCount传给expectedModCount,之后通过这两个参数的比较,可以判断集合是否可以更改。
我们知道Collection遍历有两种方法,一种是采用跟数组遍历类似的方法,如下:
//1.
List<String> strs = new List<String>(Collections.nCopies(10,"String"));
for(int i = 0; i < strs.size();i++) {
    System.out.println(strs.get(i));
    if(i %2 == 0) {
         //strs.remove(i);
    }
}

第二种就是使用迭代器:
//2.
List<String> strs = new ArrayList<String>(Collections.nCopies(10,"String")); 
 Iterator iter = strs.iterator(); 
while(iter.hasNext()) {
     System.out.println(iter.next());
     //iter.remove();
}

这两个遍历方法如果在遍历时没有从结构上对映射进行修改,是没有什么差别与问题。但是一旦在遍历的时候想要插入或删除元素时,需要注意一些问题:
方法1中,每次循环时,size()会改变,如果只需要原始的长度,则可以采用如下方法解决:
List<String> strs = new List<String>(Collections.nCopies(10,"String"));
int length = strs.size();
for(int i = 0; i < length;i++) {
    System.out.println(strs.get(i));
    if(i %2 == 0) {
         strs.remove(i);
    }
}

方法2中,每次循环时,你如果想要改变结构,需要注意的是:不能调用集合的add或remove方法,需要使用iterator的add或remove方法。
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics