这是一篇纯新手贴,欢迎拍砖。今天一个同事小王跑来问我为什么像下面程序一这样写就不会抛异常。
List<String> list = new ArrayList<String>(); list.add("1"); for(int i=0; i<list.size(); i++) { list.remove(0); }
然而向下面程序二这样写就会抛 java.util.ConcurrentModificationException 异常。
List<String> list = new ArrayList<String>(); list.add("1"); for(String str : list ){ list.remove(0); }
当时我进入List的源代码跟他解答了一下:
1,List中有一个 modCount 参数。
/** * 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;
2,当你remove的时候 modCount 的值会改变。modCount++;
(事实证明你add的时候modCount的值也会改变。)
3,for(String str : list) 用到了iterator() 方法。在 iterator.next() 操作中会调用 checkForComodification();
4,checkForComodification 的时候 会判断 modCount != expectedModCount
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
所以,由于你在for(String str : list)中改变了list的结构(remove,add等都不行),所以就会抛ConcurrentModificationException 异常了。
本以为解答清楚啦。。。。没想到我同事小王又问。。为什么? 为什么iterator() 方法中要判断modCount != expectedModCount。为什么不能在for(String str : list) 中更改list的结构。。。。。。
好吧。上网搜索Iterator的工作机制。。。。。。。Iterator是工作在一个独立的线程中,并且拥有一个 mutex锁,就是说Iterator在工作的时候,是不允许被迭代的对象被改变的。Iterator被创建的时候,建立了一个内存索引表(单链表),这个索引表指向原来的对象,当原来的对象数量改变的时候,这个索引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错误。 Iterator是一个单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始数据发生变化时,Iterator就会抛异常。
同事小王又问 为什么? 为什么Iterator是索引表没有同步改变?
那个小王他们叫我吃午饭呢。。。那个实在不行你去 Iteye 上发个帖子问问啥的。。。。。
我先吃饭去啦。。。回来再说哈。。。。。。
相关推荐
for循环语句可以嵌套使用,实现复杂的循环操作。 六、 例子 1. 求100之内各数之和 ``` for(i=1; i; i++) sum+=i; ``` 2. 把100~200之间不能被3整除的数输出 ``` for(n=100; n; n++) { if(n%3 ==0) continue...
Robot Framework 教程 - 使用For循环 在自动化测试过程中,使用For循环来对某个动作进行重复操作是很普遍的行为。在Robot Framework 中,各种测试库中均提供了多种方式的For循环结构,在其中覆盖了大部分类型的循环...
在增强for循环中,Java编译器会将其转换为一个普通的for循环,使用迭代器来遍历集合或数组。迭代器会在遍历过程中维护一个索引,指向当前要遍历的元素。这样,增强for循环可以简洁地遍历集合或数组,提高编程效率。 ...
在编程世界中,循环是一种非常基础且重要的控制流...提供的"for循环.xcodeproj"项目文件可能包含了更多具体的实例,供你实践和探索`for`循环在C语言中的实际应用。在实践中不断学习和理解,你将成为`for`循环的大师。
通过下载并研究这个“For循环”案例,你可以学习如何在Codesys中正确设置For循环参数,理解循环变量如何影响程序执行,以及如何在循环体内调用函数或指令。同时,还可以了解如何调试和优化For循环,以提高程序效率。...
`in`和`do`之间的`command1`可以是一个或多个元素,每个元素间由各种分隔符隔开,for循环会依次处理这些元素,每次处理一个,执行一次`do`后的命令。 总之,Windows bat脚本的for循环提供了灵活的循环控制,能够...
在Java编程语言中,增强的for循环(也称为foreach循环)是Java 5引入的一个重要特性,它简化了数组和集合的迭代。然而,增强for循环本身并不直接提供索引访问,这与传统的for循环不同。传统for循环可以让我们通过...
"Java增强for循环和普通for循环的比较" Java中有两种类型的for循环:普通for循环和增强for循环。普通for循环是我们最常用的循环方式,而增强for循环是一种新的循环方式,它提供了更方便的循环方式,尤其是在遍历...
### 多重For循环优化分析 #### 原始代码分析 原始代码示例如下: ```java for(int i = 0; i ; i++) { for(int j = 0; j ; j++) { for(int k = 0; k ; k++) { log(i * j * k); } } } ``` 此段代码中的嵌套循环...
JavaScript之for循环语句(源代码)JavaScript之for循环语句(源代码)JavaScript之for循环语句(源代码)JavaScript之for循环语句(源代码)JavaScript之for循环语句(源代码)JavaScript之for循环语句(源代码)JavaScript之...
例如,以下是一个使用增强 for 循环遍历 Set 集合的示例: ```java Set<String> set = new HashSet(); // ... for (String str : set) { System.out.println(str); } ``` 增强 for 循环的缺点 增强 for 循环也有...
Python中的for循环是一种控制流语句,用于遍历序列(如列表、元组、字符串)或其他可迭代对象的元素。当需要在某个循环内部再执行另一层循环时,就会用到循环的嵌套。在Python中,for循环的嵌套是完全允许的,可以将...
在本篇文档中,我们主要学习了Vue.js框架中关于for循环嵌套操作的知识点。Vue.js是一套构建用户界面的渐进式JavaScript框架,其核心库只关注视图层,易于上手,同时也能够与其它库或已有项目整合。在文档中,我们...
在Python中,可以使用`range()`函数生成一个整数序列,供`for`循环遍历,例如`for i in range(5)`会迭代0到4。 **4. 遍历字典:** 在Python中,可以使用`items()`、`keys()`或`values()`方法遍历字典的键值对、键或...
for循环会遍历这个序列,因此会执行循环体`N-1`次。 在实际应用中,for循环常用于遍历列表元素、计算累加和、实现特定的算法等。例如,计算15以内偶数的和,可以这样写: ```python sum = 0 for i in range(0, 15,...
这个练习题旨在熟悉 for 循环的基本使用,并了解如何使用 for 循环对数组进行排序。 2. 分别编写 APPLET 和 APPLICATION 程序,使运行后在屏幕上生成如下的图案。 这个练习题旨在熟悉 for 循环在图形绘制中的应用...
C#的for循环由四个部分组成,用分号分隔: 1. 初始化:定义一个或多个变量并初始化它们。 2. 条件检查:检查一个布尔表达式,如果为真,则继续执行循环;如果为假,则跳出循环。 3. 更新:更新初始化阶段定义的变量...
For循环语句的执行过程可以分为三步:首先,For循环语句会对循环变量进行初始化;其次,For循环语句会执行循环体中的代码块;最后,For循环语句会对循环变量进行更新和判断,以决定是否继续执行循环体。 四、For...
在编程语言中,`for`循环是一种常用的控制流结构,用于执行重复的代码块,通常在需要迭代或遍历序列时使用。在这个特定的例子中,我们看到的是Java中的`for`循环,它被用来计算从1到10的阶乘。 阶乘是一个数学概念...
例如,下面的代码展示了如何使用嵌套for循环来打印9x9乘法表: ```c #include int main() { for (int i = 1; i ; i++) { // 外层循环控制行 for (int j = 1; j ; j++) { // 内层循环控制列 printf("%d ", i * ...