ArrayIndexOutOfBoundsException cuando se usa el iterador de ArrayList

103

En este momento, tengo un programa que contiene un fragmento de código que se ve así:

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

¿Lo estoy haciendo bien, en lo que respecta a la iteración a través de ArrayList?

El error que recibo es:

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)

Mostraría el resto del código, pero es bastante extenso, y si no estoy haciendo la iteración correctamente, asumiría que la única posibilidad es que no estoy inicializando ArrayListcorrectamente.

Este programador
fuente
En java 8 puede utilizar el forEachmétodo: stackoverflow.com/questions/16635398/…
Vitalii Fedorenko

Respuestas:

229

¿Estoy haciendo eso bien, en lo que respecta a iterar a través de Arraylist?

No: al llamar iteratordos veces en cada iteración, obtiene nuevos iteradores todo el tiempo.

La forma más sencilla de escribir este bucle es usar la construcción for-each :

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

Como para

java.lang.ArrayIndexOutOfBoundsException: -1

Intentaste obtener el número de elemento -1de una matriz. El conteo comienza en cero.

Fred Foo
fuente
1
Úselo para cada uno, es mucho más fácil. También es posible que llame a arrayList.iterator (). Next () nuevamente y omita las entradas.
@ larsmans Ah, muchas gracias. Olvidé totalmente que puedes hacer eso con la lista de matrices. Sin embargo, lo intenté con mi código y sigo recibiendo el mismo error. Entonces creo que es un problema con la forma en que estoy agregando a arrayList anteriormente en el código, así que ahora miraré la dirección de eso. Aún así, muchas gracias por recordármelo.
Este 0ne Programmer
me encanta eso para cada operador. Uso algo parecido en rubí todo el tiempo ... do array.each |s| unless (s.nil?) end end
David West
2
Solo para notar, Have you heard ofparece un poco ofensivo (sin ninguna razón), pero no soy nativo. Por lo demás genial.
n611x007
3
@naxa: puede parecer condescendiente, he cambiado la redacción.
Fred Foo
142

Si bien estoy de acuerdo en que la respuesta aceptada suele ser la mejor solución y definitivamente más fácil de usar, noté que nadie mostró el uso adecuado del iterador. Así que aquí hay un ejemplo rápido:

Iterator<Object> it = arrayList.iterator();
while(it.hasNext())
{
    Object obj = it.next();
    //Do something with obj
}
NemesisX00
fuente
12
Siento que esto responde la pregunta con mayor precisión, ya que es un ejemplo de iterador en lugar de una solución alternativa.
sin
1
Gracias por su perspicaz respuesta. para (...) iteración suele ser la mejor solución, pero no siempre. Hoy en día, estoy buscando una sintaxis de iterador administrada explícitamente y aquí está.
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
    }
}

Pero tenga cuidado, ArrayList puede contener valores nulos . Entonces la comparación debería ser

value.equals(arrayList.get(i))

cuando esté seguro de que el valor no es nulo o debe verificar si el elemento dado es nulo.

zacheusz
fuente
10

También puedes usar así:

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

Es una buena práctica lanzar y usar el objeto. Por ejemplo, si 'arrayList' contiene una lista de objetos 'Object1'. Luego, podemos reescribir el código como:

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

También puede hacer un bucle for como lo haría con una matriz, pero en lugar de la matriz [i], usaría list.get (i)

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

Aparte de la respuesta de larsman (que de hecho es correcta), la excepción en una llamada a un método get (), por lo que el código que ha publicado no es el que está causando el error.

SJuan76
fuente
4

Manera eficiente de iterar su ArrayListseguido por este enlace . Este tipo mejorará el rendimiento del bucle durante la iteración.

int size = list.size();

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

iterar usando el iterador no es a prueba de fallas, por ejemplo, si agrega un elemento a la colección después de la creación del iterador, arrojará una excepción de modificación simultánea. Además, no es seguro para subprocesos, tienes que hacer que sea seguro para subprocesos externamente.

Por lo tanto, es mejor usar la estructura for-each de for loop. Es al menos a prueba de fallas.

Sumit Kumar Saha
fuente