为什么arrayList不在最后一个元素迭代?

时间:2016-12-09 12:24:56

标签: java arraylist collections

我尝试过以下两种情况:

    ArrayList arrayList = new ArrayList();
    arrayList.add("1");
    arrayList.add("2");
    arrayList.add("3");

    Iterator iterator = arrayList.iterator();
    while (iterator.hasNext()) {

        String value = (String) iterator.next();
        System.out.println("---->" + value);
        if (value.equals("1")) {
            arrayList.remove(0);
        }
    }

第一个场景输出是:

---->1
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at Test.main(Test.java:83)

可能导致ConcurrentModificationException例外是因为我在尝试修改集合时仍在进行迭代。

在第二种情况下,我将if()条件从value.equals("1")更改为value.equals("2"),程序不会抛出任何错误。

ArrayList arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");

Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {

    String value = (String) iterator.next();
    System.out.println("---->" + value);
    if (value.equals("2")) {
        arrayList.remove(0);
    }
}

第二种情景输出是:

---->1
---->2

在这两种情况下,我的程序都没有达到第3个元素(值:3)。

能帮助我理解这个问题吗?

5 个答案:

答案 0 :(得分:4)

问题是你要从索引0前面的列表中删除元素。而不是从列表中删除使用 iterator.remove()方法。有关详细信息,请阅读this

程序代码 -

List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");

Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
   String value = (String) iterator.next();
   System.out.println("---->" + value);
   if (value.equals("2")) {
      iterator.remove();
   }
}

为什么列表不返回最后一个元素?

回答 -

您要从列表中删除元素,并且您已针对相同列表执行迭代器操作。最后 iterator.hasnext()方法返回false,因此您没有获得最后一个元素。

如果你想看到它用于演示目的,请在下面的示例代码中运行 -

List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
    String value = (String) iterator.next();
    System.out.println("---->" + value);
    if (value.equals("2")) {
       arrayList.remove(0);
    }
}
System.out.println("ArrayList : "+arrayList);

输出 -

  

----→1

     

----> 2

     

ArrayList:[2,3]

List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");

Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
      String value = (String) iterator.next();
      System.out.println("---->" + value);
      if (value.equals("2")) {
         iterator.remove();
      }
}
System.out.println("ArrayList : "+arrayList);

输出 -

  

----→1

     

----→2

     

----→3

     

ArrayList:[1,3]

答案 1 :(得分:1)

我想你只在第一种情况下遇到问题,因为你试图删除迭代器指向的元素。实际上,第二种情况是成功的,因为您删除了第一个arraylist元素,此时此元素未被迭代器指向。

(p.s。我同意所有各种和未来的答案,它们将通过展示代码片段来描述如何解决您的问题,我只是向您提供了对发生的事情的解释)

答案 2 :(得分:1)

发生ConcurrentModificationException是因为您正在删除循环的当前迭代正在读取的相同元素(在索引0处)(值为“1”的那个)。在第二种情况下,您没有看到异常,因为您正在删除索引0处的元素,但正在读取索引1处的元素(值为“2”的元素)。除非您使用支持并发的集合之一,否则在读取元素时不能同时删除元素(请参阅java.util.concurrent包)

在迭代列表时删除元素(remove(0)),将“将列表末尾”向左移一。因此,下次检查iterator.hasNext()时,它将返回false,并且原始的第3个元素永远不会被处理。

答案 3 :(得分:0)

在迭代Collection时,应该使用迭代器删除元素:

iterator.remove()

在第二个代码中,这里:

    if (value.equals("2")) {
        arrayList.remove(0);
    }

删除列表的第一个元素。该列表的大小为2个元素 迭代器实现考虑了列表的大小,以确定它是否具有下一个元素:

public class ArrayList<E> extends AbstractList<E>
   ...
  private class Itr implements Iterator<E> {

  public boolean hasNext() {
      return cursor != size;
  }
}

由于迭代了两个元素并且列表现在的大小为2,因为你删除了它的一个元素,迭代器认为它没有下一个要迭代的元素。

如果使用迭代器删除当前元素,则没有这种副作用。

答案 4 :(得分:0)

通过在调试模式下运行两段代码,我找到了以下内容。

第一种情况:

从arraylist保存的元素:

Elements saved from arraylist

执行删除命令后

ConcurrentModificationException被抛出以下一行

String value = (String) iterator.next();

第二场景:

ArrayList与第二个链接相同。

打印2后,控件从

中断
while (iterator.hasNext())

as iterator.hasNext() = null。因此,它是安全的。