ArrayIndexOutOfBoundsException quando si utilizza l'iteratore di ArrayList


103

In questo momento, ho un programma contenente un pezzo di codice che assomiglia a questo:

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

Lo sto facendo bene, per quanto riguarda l'iterazione di ArrayList?

L'errore che ricevo è:

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)

Vorrei mostrare il resto del codice, ma è piuttosto ampio e se non sto eseguendo correttamente l'iterazione, presumo che l'unica possibilità sia che non sto inizializzando ArrayListcorrettamente.


In java 8 puoi usare il forEachmetodo: stackoverflow.com/questions/16635398/…
Vitalii Fedorenko

Risposte:


229

Lo sto facendo bene, per quanto riguarda l'iterazione nell'Arraylist?

No: chiamando iteratordue volte in ogni iterazione, ottieni sempre nuovi iteratori.

Il modo più semplice per scrivere questo ciclo è usare il costrutto for-each :

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

Quanto a

java.lang.ArrayIndexOutOfBoundsException: -1

Hai appena provato a ottenere il numero di elemento -1da un array. Il conteggio inizia da zero.


1
Usa per ciascuno, è molto più facile. Inoltre è possibile che tu abbia chiamato arrayList.iterator (). Next () di nuovo e abbia saltato le voci.

@ larsmans Ah grazie mille. Ho completamente dimenticato che potresti farlo con array List. Tuttavia, l'ho provato con il mio codice e continuo a ricevere lo stesso errore. Quindi penso che sia un problema con il modo in cui sto aggiungendo all'arrayList in precedenza nel codice, quindi ora esaminerò l'indirizzo. Tuttavia, grazie mille per avermelo ricordato.
Questo 0ne Pr0grammer

lo adoro per ogni operatore. Uso sempre qualcosa del genere in ruby ​​... do array.each |s| unless (s.nil?) end end
David West,

2
Solo per notare, Have you heard ofsembra un po 'offensivo (senza motivo), ma non sono nativo. Altrimenti fantastico.
n611x007

3
@naxa: potrebbe sembrare condiscendente, ho cambiato la formulazione.
Fred Foo

142

Sebbene sia d'accordo sul fatto che la risposta accettata sia di solito la soluzione migliore e decisamente più facile da usare, ho notato che nessuno ha mostrato l'uso corretto dell'iteratore. Quindi ecco un rapido esempio:

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

12
Mi sembra che questo risponda in modo più accurato alla domanda, poiché è un esempio iteratore invece di una soluzione alternativa.
escluso il

1
Grazie per la tua risposta perspicace. poiché (...) l'iterazione è solitamente la soluzione migliore, ma non sempre. Oggi, mi capita di cercare la sintassi dell'iteratore gestita in modo esplicito ed eccola qui.
Robert Altman

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

o

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

Ma attenzione, ArrayList può contenere valori nulli . Quindi il confronto dovrebbe essere

value.equals(arrayList.get(i))

quando sei sicuro che il valore non è nullo o dovresti controllare se l'elemento dato è nullo.


10

Puoi anche usare in questo modo:

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

È una buona pratica lanciare e utilizzare l'oggetto. Ad esempio, se "arrayList" contiene un elenco di oggetti "Object1". Quindi, possiamo riscrivere il codice come:

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

8

Potresti anche fare un ciclo for come faresti per un array, ma invece di array [i] dovresti usare list.get (i)

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

7

A parte la risposta di larsmans (che è effettivamente corretta), l'eccezione in una chiamata a un metodo get (), quindi il codice che hai postato non è quello che causa l'errore.


4

Modo efficiente per iterare il tuo ArrayListseguito da questo link . Questo tipo migliorerà le prestazioni del loop durante l'iterazione

int size = list.size();

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

2

l'iterazione utilizzando l'iteratore non è sicura, ad esempio se aggiungi un elemento alla raccolta dopo la creazione dell'iteratore, verrà generata un'eccezione di modifica simultanea. Inoltre non è thread-safe, devi renderlo thread-safe esternamente.

Quindi è meglio usare la struttura for-each del ciclo for. È almeno a prova di errore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.