并发修改异常的行为?迭代器内部如何为ArrayList工作。在第二种情况下不会抛出异常。以及为什么控制在第一种情况下进入循环,尽管迭代器已经涵盖了集合的所有元素。
//Case First
/**********Gives Concurrent Modification Exception ****/////////////
public static void main(String[] args) {
List<String> sampleList = createSampleList();
int i = 0;
for (Iterator iterator = sampleList.iterator(); iterator.hasNext();) {
i++;
System.out.println("Value of I "+i);
String value = (String) iterator.next();
if(i==sampleList.size()){
System.out.println("Removing element");
sampleList.remove(value);
}
System.out.println(value);
}
}
private static List<String> createSampleList(){
List<String> sampleList = new ArrayList<String>();
sampleList.add("one");
sampleList.add("two");
sampleList.add("three");
sampleList.add("four");
sampleList.add("five");
return sampleList;
}
/**Output**/
Value of I 1
one
Value of I 2
two
Value of I 3
three
Value of I 4
four
Value of I 5
Removing element
five
Value of I 6
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at com.collection.iterator.Test.main(Test.java:17)
/**Output**/
//Second Case
/**********Does not Give Concurrent Modification *******/////////////
public static void main(String[] args) {
List<String> sampleList = createSampleList();
int i = 0;
for (Iterator iterator = sampleList.iterator(); iterator.hasNext();) {
i++;
System.out.println("Value of I "+i);
String value = (String) iterator.next();
if(i==sampleList.size()-1){
System.out.println("Removing element");
sampleList.remove(value);
}
System.out.println(value);
}
}
private static List<String> createSampleList(){
List<String> sampleList = new ArrayList<String>();
sampleList.add("one");
sampleList.add("two");
sampleList.add("three");
sampleList.add("four");
sampleList.add("five");
return sampleList;
}
/**Output**/
Value of I 1
one
Value of I 2
two
Value of I 3
three
Value of I 4
Removing element
four
/**Output**/
答案 0 :(得分:1)
我得到了答案。 实际上,答案在于在ArrayList中实现迭代器。
第一种情况://每个人都知道为什么它会抛出异常,因为我们正在改变除了iterator.remove方法之外的集合结构。 但问题是:虽然它已经打印了所有五个元素,但它再次进入循环并抛出异常。 下面是iterator的hasNext()方法的实现。因此它检查游标(迭代器在迭代元素时维护游标),其大小为arraylist。在第一个案例中,在达到第五个元素后,光标变为5 ,我们从arraylist 中删除了一个元素,因此大小变为4 。所以在循环中,hasnext()方法被调用后,它返回true并进入循环。
public boolean hasNext() {
return (this.cursor != ArrayList.this.size);
}
这也解释了为什么在第二种情况下不抛出异常,因为当我们删除了第4个元素时,游标值为4,并且ArrayList大小也变为4.在这种情况下,下一个返回false并且它不会进入循环而不会next()方法实际上抛出ConcurrentModificationException。