Java 循环遍历集合,避免在删除循环中的对象时出现ConcurrentModificationException

Java 循环遍历集合,避免在删除循环中的对象时出现ConcurrentModificationException,java,collections,iteration,Java,Collections,Iteration,我们都知道您无法执行以下操作,因为ConcurrentModificationException: for (Object i : l) { if (condition(i)) { l.remove(i); } } 但这显然有时有效,但并不总是有效。下面是一些特定的代码: publicstaticvoidmain(字符串[]args){ 集合l=新的ArrayList(); 对于(int i=0;i

我们都知道您无法执行以下操作,因为
ConcurrentModificationException

for (Object i : l) {
    if (condition(i)) {
        l.remove(i);
    }
}
但这显然有时有效,但并不总是有效。下面是一些特定的代码:

publicstaticvoidmain(字符串[]args){
集合l=新的ArrayList();
对于(int i=0;i<10;++i){
l、 增加(4);
l、 增加(5);
l、 增加(6);
}
对于(int i:l){
如果(i==5){
l、 删除(i);
}
}
系统输出打印LN(l);
}
当然,这会导致:

Exception in thread "main" java.util.ConcurrentModificationException
即使多个线程没有这样做。无论如何

这个问题的最佳解决方案是什么?如何在循环中从集合中移除项而不引发此异常

我在这里也使用了任意的
集合
,而不一定是
数组列表
,因此您不能依赖
获取
,这是有效的:

Iterator<Integer> iter = l.iterator();
while (iter.hasNext()) {
    if (iter.next() == 5) {
        iter.remove();
    }
}
Iterator iter=l.Iterator();
while(iter.hasNext()){
if(iter.next()==5){
iter.remove();
}
}
我假设因为foreach循环是迭代的语法糖,所以使用迭代器不会有帮助。。。但是它提供了这个
.remove()
功能。

这个功能:

Iterator<Integer> iter = l.iterator();
while (iter.hasNext()) {
    if (iter.next() == 5) {
        iter.remove();
    }
}
Iterator iter=l.Iterator();
while(iter.hasNext()){
if(iter.next()==5){
iter.remove();
}
}
我假设因为foreach循环是迭代的语法糖,所以使用迭代器不会有帮助。。。但是它提供了这个
.remove()
功能。

是安全的,您可以这样使用它:

List<String> list = new ArrayList<>();

// This is a clever way to create the iterator and call iterator.hasNext() like
// you would do in a while-loop. It would be the same as doing:
//     Iterator<String> iterator = list.iterator();
//     while (iterator.hasNext()) {
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
    String string = iterator.next();
    if (string.isEmpty()) {
        // Remove the current element from the iterator and the list.
        iterator.remove();
    }
}
List List=new ArrayList();
//这是一种创建迭代器并调用iterator.hasNext()的聪明方法
//您可以在一个while循环中完成。这与执行以下操作相同:
//迭代器迭代器=list.Iterator();
//while(iterator.hasNext()){
for(Iterator Iterator=list.Iterator();Iterator.hasNext();){
String字符串=迭代器.next();
if(string.isEmpty()){
//从迭代器和列表中删除当前元素。
iterator.remove();
}
}
请注意,这是在迭代过程中修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改基础集合,则该行为未指定

资料来源:


同样,如果您有一个
列表迭代器
,并且想要添加项目,那么您可以使用,原因与您可以使用
迭代器#remove
的原因相同-它的设计允许它


在您的情况下,您试图从列表中删除,但如果在迭代其内容时尝试将放入映射,则同样的限制适用。

是安全的,您可以这样使用它:

List<String> list = new ArrayList<>();

// This is a clever way to create the iterator and call iterator.hasNext() like
// you would do in a while-loop. It would be the same as doing:
//     Iterator<String> iterator = list.iterator();
//     while (iterator.hasNext()) {
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
    String string = iterator.next();
    if (string.isEmpty()) {
        // Remove the current element from the iterator and the list.
        iterator.remove();
    }
}
List List=new ArrayList();
//这是一种创建迭代器并调用iterator.hasNext()的聪明方法
//您可以在while循环中执行。这与执行以下操作相同:
//迭代器迭代器=list.Iterator();
//while(iterator.hasNext()){
for(Iterator Iterator=list.Iterator();Iterator.hasNext();){
String字符串=迭代器.next();
if(string.isEmpty()){
//从迭代器和列表中删除当前元素。
iterator.remove();
}
}
请注意,这是在迭代过程中修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改基础集合,则该行为未指定

资料来源:


同样,如果您有一个
列表迭代器
,并且想要添加项目,那么您可以使用,原因与您可以使用
迭代器#remove
的原因相同-它的设计允许它



在您的情况下,您试图从列表中删除,但如果在迭代内容时尝试将放入映射,则相同的限制适用。

您可以像您提到的那样直接使用迭代器,或者保留第二个集合,并将要删除的每个项目添加到新集合中,然后在这允许您以增加内存使用和cpu时间为代价,继续使用for-each循环的类型安全性(除非您有非常非常大的列表或非常旧的计算机,否则这不会是一个大问题)

publicstaticvoidmain(字符串[]args)
{
集合l=新的ArrayList();
Collection itemsToRemove=new ArrayList();
对于(int i=0;i<10;i++){
l、 加(4的整数);
l、 加(5的整数);
l、 加(6的整数);
}
for(整数i:l)
{
如果(i.intValue()==5){
itemsToRemove.add(i);
}
}
l、 removeAll(itemsToRemove);
系统输出打印LN(l);
}

您可以像前面提到的那样直接使用迭代器,或者保留第二个集合,将要删除的每个项添加到新集合中,然后在最后删除所有项。这允许您继续使用for each循环的类型安全性,但会增加内存使用和cpu时间(除非您有非常非常大的列表或非常旧的计算机,否则这不会是一个大问题)

publicstaticvoidmain(字符串[]args)
{
集合l=新的ArrayList();
Collection itemsToRemove=new ArrayList();
对于(int i=0;i<10;i++){
l、 加(4的整数);
l、 加(5的整数);
l、 加(6的整数);
}
for(整数i:l)
{
如果(i.intValue()==5){
itemsToRemove.add(i);
}
}
l、 removeAll(itemsToRemove);
系统输出打印LN(l);
}

既然这个问题已经得到了回答,也就是说,最好的方法是使用迭代器对象的remove方法,那么我将详细介绍抛出错误的位置
“java.util.ConcurrentModificationException”

每个集合类都有一个私有类,它实现迭代器接口,并提供诸如
next()
remove()
之类的方法
final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}
for (String str : new ArrayList<String>(listOfStr))     
{
    listOfStr.remove(/* object reference or index */);
}
MutableList<Integer> list = Lists.mutable.of(1, 2, 3, 4, 5);
list.removeIf(Predicates.lessThan(3));
Assert.assertEquals(Lists.mutable.of(3, 4, 5), list);
MutableList<Integer> list = Lists.mutable.of(1, 2, 3, 4, 5);
list.removeIf(Predicates.cast(integer -> integer < 3));
Assert.assertEquals(Lists.mutable.of(3, 4, 5), list);
for (Iterator<Object> it = objects.iterator(); it.hasNext();) {
    Object object = it.next();
    if (test) {
        it.remove();
    }
}
//"list" is ArrayList<Object>
//"state" is some boolean variable, which when set to true, Object will be removed from the list
int index = 0;
while(index < list.size()) {
    Object r = list.get(index);
    if( state ) {
        list.remove(index);
        index = 0;
        continue;
    }
    index += 1;
}
Collection<Integer> coll = new ArrayList<>();
//populate

coll.removeIf(i -> i == 5);
for(int i = l.size() - 1; i >= 0; i --) {
  if (l.get(i) == 5) {
    l.remove(i);
  }
}
//region prepare data
ArrayList<Integer> ints = new ArrayList<Integer>();
ArrayList<Integer> toRemove = new ArrayList<Integer>();
Random rdm = new Random();
long millis;
for (int i = 0; i < 100000; i++) {
    Integer integer = rdm.nextInt();
    ints.add(integer);
}
ArrayList<Integer> intsForIndex = new ArrayList<Integer>(ints);
ArrayList<Integer> intsDescIndex = new ArrayList<Integer>(ints);
ArrayList<Integer> intsIterator = new ArrayList<Integer>(ints);
//endregion

// region for index
millis = System.currentTimeMillis();
for (int i = 0; i < intsForIndex.size(); i++) 
   if (intsForIndex.get(i) % 2 == 0) intsForIndex.remove(i--);
System.out.println(System.currentTimeMillis() - millis);
// endregion

// region for index desc
millis = System.currentTimeMillis();
for (int i = intsDescIndex.size() - 1; i >= 0; i--) 
   if (intsDescIndex.get(i) % 2 == 0) intsDescIndex.remove(i);
System.out.println(System.currentTimeMillis() - millis);
//endregion

// region iterator
millis = System.currentTimeMillis();
for (Iterator<Integer> iterator = intsIterator.iterator(); iterator.hasNext(); )
    if (iterator.next() % 2 == 0) iterator.remove();
System.out.println(System.currentTimeMillis() - millis);
//endregion
for (Integer i : l)
{
    if (i.intValue() == 5){
            itemsToRemove.add(i);
            break;
    }
}
List<Car> cars = ArrayList<>();
// add cars here...

for (ListIterator<Car> carIterator = cars.listIterator();  carIterator.hasNext(); )
{
   if (<some-condition>)
   { 
      carIterator().remove()
   }
   else if (<some-other-condition>)
   { 
      carIterator().add(aNewCar);
   }
}
public class Example {
    private final List<String> queue = Collections.synchronizedList(new ArrayList<String>());

    public void removeFromQueue() {
        synchronized (queue) {
            Iterator<String> iterator = queue.iterator();
            String string = iterator.next();
            if (string.isEmpty()) {
                iterator.remove();
            }
        }
    }
}
Collection<Integer> l = new ArrayList<Integer>();

for (int i=0; i < 10; ++i) {
    l.add(new Integer(4));
    l.add(new Integer(5));
    l.add(new Integer(6));
}

l.removeIf(i -> i.intValue() == 5);
final List<Integer> list = new ArrayList<>();
for(int i = 0; i < 10; ++i){
    list.add(i);
}

int i = 1;
while(i < list.size()){
    if(list.get(i) % 2 == 0){
        list.remove(i++);

    } else {
        i += 2;
    }
}
final List<Integer> list = new ArrayList<>();
for(int i = 0; i < 10; ++i){
    list.add(i);
}

int i = 0;
while(i < list.size()){
    if(list.get(i) % 2 == 0){
        list.remove(i);

    } else {
        ++i;
    }
}
int n = list.size();
for(int j=0;j<n;j++){
    //you can also put a condition before remove
    list.remove(0);
    Collections.rotate(list, 1);
}
Collections.rotate(list, -1);
for (Object i : l) {
    if (condition(i)) {
        l = (l.stream().filter((a) -> a != i)).collect(Collectors.toList());
    }
}
l.removeIf(current -> current == 5);
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while(iterator.hasNext()){
    Map.Entry<String, String> entry = iterator.next();
    if(entry.getKey().equals("test")) {
        iterator.remove();
    } 
}
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String value = iter.next()
    if (value == "A") {
        //throws ConcurrentModificationException
        list.remove(it.next());
    }
}
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String value = iter.next()
    if (value == "A") {
        it.remove()
    }
}