使用ArrayList迭代器时出现ArrayIndexOutOfBoundsException错误

102

现在,我的程序包含了一段代码,看起来像这样:

while (arrayList.iterator().hasNext()) {
     //value is equal to a String value
     if( arrayList.iterator().next().equals(value)) {
          // do something 
     }
}

我在遍历ArrayList方面做得对吗?

我收到的错误信息是:

java.lang.ArrayIndexOutOfBoundsException: -1
    at java.util.ArrayList.get(Unknown Source)
    at main1.endElement(main1.java:244)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at javax.xml.parsers.SAXParser.parse(Unknown Source)
    at javax.xml.parsers.SAXParser.parse(Unknown Source)
    at main1.traverse(main1.java:73)
    at main1.traverse(main1.java:102)
    at main1.traverse(main1.java:102)
    at main1.main(main1.java:404)

我想展示其余的代码,但是它非常广泛,如果我没有正确执行迭代,我会认为唯一的可能性是我没有正确初始化ArrayList


在Java 8中,您可以使用forEach方法:https://dev59.com/o2Qn5IYBdhLWcg3wr446 - Vitalii Fedorenko
8个回答

229

我对于ArrayList的遍历方式是否正确?

不正确:在每次迭代中调用两次iterator,你会一直得到新的迭代器。

使用最简单的方式来编写这个循环是使用for-each语法结构:

for (String s : arrayList)
    if (s.equals(value))
        // ...

关于

java.lang.ArrayIndexOutOfBoundsException: -1

你刚刚尝试从数组中获取第-1个元素。计数从零开始。


1
使用 for-each 循环更容易。还有可能你调用了 arrayList.iterator().next(),跳过了某些元素。 - user500074
@ larsmans 啊,非常感谢。我完全忘记了你可以用ArrayList来做到这一点。然而,我尝试了我的代码,但仍然出现相同的错误。所以我认为问题在于我之前在代码中添加ArrayList的方式,所以我现在会去解决这个问题。还是非常感谢你提醒我。 - This 0ne Pr0grammer
喜欢每个操作符。我经常在Ruby中使用类似的东西...array.each do |s| unless (s.nil?) end end - David West
2
只是提醒一下,“你听说过”这个短语似乎有点冒犯(没有理由),但我不是本地人。除此之外很好。 - n611x007
3
@naxa说:“这可能会让人感到居高临下,我已经改变措辞了。” - Fred Foo

142

虽然我也同意通常接受的答案是最好的解决方案并且更容易使用,但我注意到没有人显示迭代器的正确用法。因此,这里是一个快速示例:

Iterator<Object> it = arrayList.iterator();
while(it.hasNext())
{
    Object obj = it.next();
    //Do something with obj
}

12
我觉得这更准确地回答了问题,因为它是一个迭代器示例而不是另一种解决方案。 - withoutclass
1
感谢您的深入回答。for(...)迭代通常是最好的解决方案,但并非总是如此。今天,我碰巧正在寻找明确管理的迭代器语法,而这里就有了。 - Robert Altman

37
List<String> arrayList = new ArrayList<String>();
for (String s : arrayList) {
    if(s.equals(value)){
        //do something
    }
}
或者
for (int i = 0; i < arrayList.size(); i++) {
    if(arrayList.get(i).equals(value)){
        //do something
    }
}

但要注意,ArrayList可以容纳null值。因此比较应该是

value.equals(arrayList.get(i))

当你确定值不为null时,或者你需要检查给定元素是否为null。


10

你也可以这样使用:

for(Iterator iterator = arrayList.iterator(); iterator.hasNext();) {
x = iterator.next();
//do some stuff
}

将对象进行类型转换并使用是一个好的编程实践。例如,如果“arrayList”包含一组“Object1”对象,那么我们可以将代码重写为:

这是一个良好的实践,将对象进行强制类型转换并使用。例如,如果“arrayList”包含一系列“Object1”对象,则可以重写代码如下:

for(Iterator iterator = arrayList.iterator(); iterator.hasNext();) {
x = (Object1) iterator.next();
//do some stuff
}

8
您可以像处理数组一样使用for循环,但是不需要使用array[i],而是使用list.get(i)。
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

7
除了larsmans的答案(他确实是正确的),调用get()方法时会出现异常,所以您发布的代码不是导致错误的代码。

4

这是一个迭代 ArrayList 的高效方法,参考这个链接。使用这种方式可以提高循环迭代的性能。

int size = list.size();

for(int j = 0; j < size; j++) {
    System.out.println(list.get(i));
}

2
使用迭代器进行迭代不是安全的,例如如果在创建迭代器后向集合中添加元素,则会抛出ConcurrentModificationException异常。此外,它也不是线程安全的,你需要在外部使它线程安全。

因此最好使用for-each循环结构进行迭代,这至少是安全的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接