java for-each的本质是使用迭代器实现
1.案例
@Test
public void testForEach() {
List<String> strLinkedList = new LinkedList<>();
strLinkedList.add("aaaa");
strLinkedList.add("bbb");
strLinkedList.add("cccc");
System.out.println("strLinkedList.size:" + strLinkedList.size());
for (String str : strLinkedList) {
System.out.println("strLinkedList.size:" + strLinkedList.size());
if (str.equals("aaaa")) {
strLinkedList.remove("aaaa");//error,ConcurrentModificationException
}else if(str.equals("cccc")){
strLinkedList.remove("cccc");//error,ConcurrentModificationException
}
str = "mmmm";//ok
}
}
2.上面的代码会报ConcurrentModificationException异常
3.原因分析
每次进入for (String str : strLinkedList) 时,会调用java.util.LinkedList.ListItr.next()方法;
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}
下面看一下checkForComodification()方法
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
因为checkForComodification()方法对集合的长度进行了判断,所以出现异常
4.躲避长度判断,执行增加和删除的方法。
在下一次进入循环之前就退出循环,这样就能既能实现增加和删除操作,又不会报错
@Test
public void testForEach() {
List<String> strLinkedList = new LinkedList<>();
strLinkedList.add("aaaa");
strLinkedList.add("bbb");
strLinkedList.add("cccc");
System.out.println("strLinkedList.size:" + strLinkedList.size());
for (String str : strLinkedList) {
if (str.equals("bbb")) {
strLinkedList.remove("aaaa");// OK
System.out.println("strLinkedList.size:" + strLinkedList.size());
break;
}
}
System.out.println("strLinkedList.size:" + strLinkedList.size());
}
输出结果
strLinkedList.size:3
strLinkedList.size:2
strLinkedList.size:2
java for-each的本质是使用迭代器实现