不知道大家遇到过这样 的代码段没有
List<String> list = new LinkedList<String>(); list.add("A"); list.add("B"); list.add("C"); Iterator<String> iterator = list.iterator(); while(iterator.hasNext()) { list.add("D"); /* list.set(0,"AA");*/ System.out.println(iterator.next()); }
我就曾经无意之中写过这样的代码段,程序在运行的时候报错java.util.ConcurrentModificationException。打开源码发现,每次在迭代器生成之后,要是用list.add() list.remove()方法改变链表或者数组的结构,迭代器操作都会报这个错误。我们贴出来源码看看为啥。
public E next() { checkForComodification();(0) if (!hasNext()) throw new NoSuchElementException(); lastReturned = next;(1) next = next.next; nextIndex++;(2) return lastReturned.item; }
(0)这个过程就是跑错的地方,也就是说迭代器不允许我们再修改被引用的链表结构。 next、nextIndex都是初始化迭代器的时候赋值的。
ListItr(int index) { // assert isPositionIndex(index); next = (index == size) ? null : node(index); nextIndex = index; }
如果没有(0),我们用list.add("D"); 这样的代码改变了原来的list结构,那么(2)中的
nextIndex
不会是原来的值了。这样就会导致取值混乱。
举个栗子
链表
1--》2--》3--》4
在迭代器到达2的时候,用add方法在2之前给链表添加一个值
1--》D-->2--》3--》4而此时nextIndex依然在2,下次获取值又获取到了数据2,导致遍历链表数据混乱。所以在迭代器创建之后,不允许再修改被引用链表的结构。另外,迭代器是非线程安全的,api建议我们使用 List list = Collections.synchronizedList(new LinkedList(...))
保证线程安全。
时间: 2024-11-06 10:19:52