ArrayIndexOutOfBoundsException bei Verwendung des Iterators der ArrayList


103

Im Moment habe ich ein Programm, das einen Code enthält, der so aussieht:

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

Mache ich das richtig, was das Durchlaufen der ArrayList angeht?

Der Fehler, den ich bekomme, ist:

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)

Ich würde den Rest des Codes zeigen, aber er ist ziemlich umfangreich, und wenn ich die Iteration nicht richtig mache, würde ich annehmen, dass die einzige Möglichkeit darin besteht, dass ich den Code nicht ArrayListrichtig initialisiere .


In Java 8 können Sie die forEachMethode verwenden: stackoverflow.com/questions/16635398/…
Vitalii Fedorenko

Antworten:


229

Mache ich das richtig, was das Durchlaufen der Arrayliste angeht?

Nein: Wenn Sie iteratorin jeder Iteration zweimal aufrufen , erhalten Sie ständig neue Iteratoren.

Der einfachste Weg, diese Schleife zu schreiben, ist die Verwendung des for-each- Konstrukts:

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

Wie für

java.lang.ArrayIndexOutOfBoundsException: -1

Sie haben gerade versucht, die Elementnummer -1aus einem Array abzurufen. Die Zählung beginnt bei Null.


1
Verwenden Sie für jeden, es ist viel einfacher. Es ist auch möglich, dass Sie arrayList.iterator (). Next () erneut aufgerufen und Einträge übersprungen haben.

@ larsmans Ah vielen Dank. Ich habe völlig vergessen, dass Sie das mit Array List machen können. Ich habe dies jedoch mit meinem Code versucht und erhalte immer noch den gleichen Fehler. Ich denke, es ist ein Problem damit, wie ich die ArrayList früher im Code hinzufüge, also werde ich mir jetzt die Adresse ansehen. Trotzdem vielen Dank, dass Sie mich daran erinnert haben.
Diese 0ne Pr0grammer

Ich liebe das für jeden Bediener. Ich benutze so etwas die ganze Zeit in Rubin ... do array.each |s| unless (s.nil?) end end
David West

2
Nur zu bemerken, Have you heard ofscheint irgendwie beleidigend (ohne Grund), aber ich bin nicht einheimisch. Ansonsten super.
n611x007

3
@naxa: es kann herablassend wirken, ich habe den Wortlaut geändert.
Fred Foo

142

Obwohl ich der Meinung bin, dass die akzeptierte Antwort normalerweise die beste Lösung ist und definitiv einfacher zu verwenden ist, habe ich festgestellt, dass niemand die richtige Verwendung des Iterators angezeigt hat. Hier ist ein kurzes Beispiel:

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

12
Ich bin der Meinung, dass dies die Frage genauer beantwortet, da es sich um ein Iterator-Beispiel anstelle einer alternativen Lösung handelt.
Klasse

1
Vielen Dank für Ihre aufschlussreiche Antwort. für (...) Iteration ist normalerweise die beste Lösung, aber nicht immer. Heute suche ich zufällig nach explizit verwalteter Iteratorsyntax und hier ist sie.
Robert Altman

37
List<String> arrayList = new ArrayList<String>();
for (String s : arrayList) {
    if(s.equals(value)){
        //do something
    }
}

oder

for (int i = 0; i < arrayList.size(); i++) {
    if(arrayList.get(i).equals(value)){
        //do something
    }
}

Aber seien Sie vorsichtig. ArrayList kann Nullwerte enthalten . Vergleich sollte also sein

value.equals(arrayList.get(i))

Wenn Sie sicher sind, dass der Wert nicht null ist, oder wenn Sie überprüfen sollten, ob das angegebene Element null ist.


10

Sie können auch wie folgt verwenden:

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

Es ist eine gute Praxis, das Objekt zu gießen und zu verwenden. Zum Beispiel, wenn die 'arrayList' eine Liste von 'Object1'-Objekten enthält. Dann können wir den Code wie folgt neu schreiben:

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

8

Sie können auch eine for-Schleife wie für ein Array ausführen, aber anstelle von array [i] würden Sie list.get (i) verwenden.

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

7

Abgesehen von der Antwort von larsmans (wer ist in der Tat richtig) ist die Ausnahme bei einem Aufruf einer get () -Methode, sodass der von Ihnen veröffentlichte Code nicht derjenige ist, der den Fehler verursacht.


4

Effizient zu Iterierte Ihr ArrayListvon diesem gefolgt Link . Dieser Typ verbessert die Leistung der Schleife während der Iteration

int size = list.size();

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

2

Das Iterieren mit dem Iterator ist nicht ausfallsicher. Wenn Sie beispielsweise nach der Erstellung des Iterators ein Element zur Sammlung hinzufügen, wird eine gleichzeitige Modifikationsausnahme ausgelöst. Außerdem ist es nicht threadsicher, Sie müssen es extern threadsicher machen.

Daher ist es besser, für jede Struktur eine for-Schleife zu verwenden. Es ist zumindest ausfallsicher.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.