使用ArrayList的迭代器时出现ArrayIndexOutOfBoundsException


103

现在,我有一个包含以下代码的程序:

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:方法stackoverflow.com/questions/16635398/...
维塔利费德林

Answers:


229

就遍历Arraylist而言,我这样做是否正确?

否:通过iterator在每次迭代中调用两次,您将始终获得新的迭代器。

编写此循环的最简单方法是使用for-each构造:

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

至于

java.lang.ArrayIndexOutOfBoundsException: -1

您只是试图-1从数组中获取元素编号。计数从零开始。


1
使用for-each,它要容易得多。也有可能您再次调用arrayList.iterator()。next()并跳过了条目。

@larsmans啊非常感谢你。我完全忘记了您可以使用数组List来做到这一点。但是,我用代码尝试了这一点,但仍然遇到相同的错误。所以我认为这是我在代码前面如何添加到arrayList的问题,所以现在我来看一下该地址。不过,还是非常感谢您提醒我有关此事。
这个0ne Pr0grammer 2011年

喜欢每个操作员。我一直在红宝石中使用类似的东西…… do array.each |s| unless (s.nil?) end end
David West

2
只是要注意,Have you heard of似乎有点冒犯(无缘无故),但我不是本地人。否则很棒。
n611x007

3
@naxa:它可能是居高临下的,我改变了措辞。
弗雷德·富

142

虽然我同意公认的答案通常是最佳解决方案,并且绝对易于使用,但我注意到没有人显示出正确使用了迭代器。所以这是一个简单的例子:

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

12
我觉得这样可以更准确地回答问题,因为它是一个迭代器示例,而不是替代解决方案。
2013年

1
感谢您的有见地的回应。for(...)迭代通常是最佳解决方案,但并非总是如此。今天,我碰巧正在寻找显式管理的迭代器语法,就在这里。
罗伯特·奥特曼

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”对象的列表。然后,我们可以将代码重新编写为:

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

8

您也可以像处理数组一样进行for循环,但可以使用list.get(i)代替array [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

使用迭代器进行迭代并非是不安全的,例如,如果在创建迭代器之后将元素添加到集合中,则它将引发并发修改异常。而且它不是线程安全的,您必须使其在外部线程安全。

因此,最好使用for循环的for-each结构。它至少具有故障保护功能。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.