1. List 迭代过程中删除元素采用list.remove(obj)会造成其size自减,modCount自增而产生问题:
Collection list = new ArrayList();
list.add("creek");
list.add("misty");
list.add("forest");
Iterator iter = list.iterator();
while (iter.hasNext()) {
Object obj = iter.next();
if ("creek".equals(obj))
list.remove(obj);
}
运行时会报
java.util.ConcurrentModificationException错误。
我们先看看java.util.ArrayList的相关代码:
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
还有java.util.AbstractList的:
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
checkForComodification();
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
当调用iterator()方法的时候,expectedModCount = modCount (等于3,三次添加元素)
第一次循环的时候,把第一个元素给删除了,这时modCount++ (等于4)
第二次调用iter.next()会调用checkForComodification()方法,check到这两个值不相等,所以报异常。
如果我们需要在迭代的过程中对元素进行删除操作,使用AbstractList提供的remove()方法,当然这也不是线程安全的:
public void remove() {
if (lastRet == -1)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
// Let the values of the two variables be equal
// so that the check would be passed
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
可以看到这里的expectedModCount已经设置成和modCount相等了。
另一种方式是利用并发库里的CopyOnWriteArrayList类:
Collection list = new CopyOnWriteArrayList();
...
2. List 迭代过程中添加元素采用list.add(obj)会造成其size自增,modCount自增而产生问题,这里就不再赘述。
分享到:
相关推荐
当你想在迭代过程中删除元素时,应该使用`Iterator`的`remove()`方法,而不是直接调用集合的`remove()`方法。这样,`Iterator`会正确处理集合的内部状态,避免异常: ```java List<String> list = new ArrayList...
在Java编程语言中,LinkedList是一种线性数据结构,属于集合框架的一部分,实现了List接口和Deque接口。LinkedList以链表的形式存储元素,这使得它在添加和删除元素时具有较高的效率,尤其是在列表的中间或开头进行...
4. **push_back和push_front方法**:分别在`list`的末尾和开头添加元素。 5. **remove和remove_if方法**:用于删除满足条件的元素。如`c1.remove(10);` 删除所有值为10的元素。 6. **reverse方法**:反转`list`中的...
值得注意的是,迭代器提供了`remove()`方法,允许在遍历过程中安全地删除元素。如果在调用`remove()`之前没有调用`next()`,或者在没有更多元素的情况下调用`remove()`,那么会抛出`NoSuchElementException`。此外,...
在当前循环位置之后添加元素时,循环将继续进行处理,就好像它们从一开始就存在一样。 当前循环位置之前添加的元素将被跳过。 在当前循环位置之前删除的元素不会对循环产生影响。 在当前循环位置之后删除的元素将...
在Java编程中,`ListIterator`是`List`接口提供的一种特殊的迭代器,它具有双向遍历的能力,不仅可以向前遍历列表,还可以向后遍历。`ListIterator`还提供了在遍历过程中添加、修改和删除元素的功能,使得对列表的...
// 如果在迭代过程中需要删除元素,应使用iterator.remove(),而非list.remove() if ("Element1".equals(element)) { iterator.remove(); } } ``` 上述代码展示了如何使用迭代器遍历并可能删除List中的元素。...
1. **迭代器(Iterator)**:迭代器接口,定义了遍历元素的方法,如`hasNext()`用于检查是否还有更多元素,`next()`用于获取下一个元素,以及可能存在的`remove()`方法用于删除当前元素。 2. **聚合对象(Colllection)*...
Java中的`Iterator`接口是Java... 可能这个图片文件是用来辅助理解`Iterator`概念的,比如它可能包含了一个迭代过程的流程图或示例代码的截图。在实际学习中,视觉辅助材料可以帮助我们更好地理解和记忆复杂的概念。
4. **避免在循环中插入或删除元素**:尽可能地将插入和删除操作移到循环之外,或者使用其他容器,如`list`,其迭代器在插入和删除时不会失效。 在给定的测试用例"InvalidIteratorTest"中,可能包含了模拟这些情况的...
- `erase()`:删除list中的一个或多个元素。 - `remove()`:根据给定值从list中移除所有匹配项。 - `remove_if()`:根据给定的条件从list中移除所有匹配项。 - `resize()`:改变list的大小。 - `swap()`:交换...
然而,在使用`forEach`循环时,直接尝试修改遍历的集合(例如删除或添加元素)是不被允许的,因为这会导致`ConcurrentModificationException`异常。本文将探讨在使用`forEach`循环中遇到无法删除元素的问题,并提供...
在示例代码中,`ConcreteAggregate`类使用`List`作为数据存储,提供了添加元素、获取元素数量以及根据索引获取元素的能力。 #### 4. 具体迭代器(ConcreteIterator) 具体迭代器实现了迭代器接口,并与具体的聚合...
添加、删除元素的方法 public IEnumerator<int> GetEnumerator() { return items.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } ``` 2. **实现迭代器**:...
在迭代器遍历过程中,对集合进行修改(如添加或删除元素)可能会影响迭代器的行为。例如,如果在调用`next()`之后调用`remove()`,则通常不会有问题。但是,在调用`hasNext()`或`next()`之前删除元素可能会导致...
迭代器提供了一个`remove()`方法,允许在遍历过程中删除当前元素。需要注意的是,调用`remove()`方法前必须先调用过一次`next()`方法,否则会抛出`IllegalStateException`异常。例如: ```java while (iterator....
4. 创建具体聚合类,实现抽象聚合类的方法,包括存储元素、添加元素、删除元素等,并实现`createIterator()`方法,返回具体的迭代器实例。 5. 在客户端代码中,通过调用聚合对象的`createIterator()`方法获取迭代器...
- 如果在迭代过程中添加或删除元素,建议使用`Iterator`的`remove()`方法,而不是集合的`add()`或`remove()`方法,以避免并发修改异常。 总结来说,Java中的迭代器设计模式是集合操作的重要组成部分,它允许程序员...
学习这个教程,你将掌握Java List接口的基础知识,包括如何创建List、添加元素、遍历列表以及如何在遍历过程中安全地移动元素。这将有助于你在实际项目中更有效地处理数据结构和算法问题。同时,提供的源代码实例将...