ArrayIndexOutOfBoundsException lors de l'utilisation de l'itérateur de ArrayList

103

En ce moment, j'ai un programme contenant un morceau de code qui ressemble à ceci:

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

Est-ce que je fais cela correctement, en ce qui concerne l'itération dans ArrayList?

L'erreur que j'obtiens est:

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)

Je montrerais le reste du code, mais c'est assez étendu, et si je ne fais pas l'itération correctement, je suppose que la seule possibilité est que je ne l'initialise pas ArrayListcorrectement.

Ce 0ne Pr0grammer
la source
Dans java 8, vous pouvez utiliser la forEachméthode: stackoverflow.com/questions/16635398/…
Vitalii Fedorenko

Réponses:

229

Est-ce que je fais ça correctement, en ce qui concerne l'itération dans l'Arraylist?

Non: en appelant iteratordeux fois à chaque itération, vous obtenez de nouveaux itérateurs tout le temps.

Le moyen le plus simple d'écrire cette boucle consiste à utiliser la construction for-each :

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

Pour ce qui est de

java.lang.ArrayIndexOutOfBoundsException: -1

Vous venez d'essayer d'obtenir le numéro d'élément -1d'un tableau. Le comptage commence à zéro.

Fred Foo
la source
1
Utilisez pour chacun, c'est beaucoup plus facile. Il est également possible que vous ayez à nouveau appelé arrayList.iterator (). Next () et que vous ayez ignoré des entrées.
@ larsmans Ah merci beaucoup. J'ai totalement oublié que vous pouviez le faire avec array List. Cependant, j'ai essayé cela avec mon code et j'obtiens toujours la même erreur. Donc, je pense que c'est un problème avec la façon dont j'ajoute à la arrayList plus tôt dans le code, donc je vais maintenant examiner cela. Pourtant, merci beaucoup de me l'avoir rappelé.
This 0ne Pr0grammer le
j'adore ça pour chaque opérateur. J'utilise quelque chose comme ça en rubis tout le temps ... do array.each |s| unless (s.nil?) end end
David West
2
Juste pour noter, cela Have you heard ofsemble assez offensant (sans raison), mais je ne suis pas natif. Sinon super.
n611x007
3
@naxa: cela peut paraître condescendant, j'ai changé la formulation.
Fred Foo
142

Bien que je convienne que la réponse acceptée est généralement la meilleure solution et certainement plus facile à utiliser, je n'ai remarqué que personne n'a affiché l'utilisation appropriée de l'itérateur. Voici donc un exemple rapide:

Iterator<Object> it = arrayList.iterator();
while(it.hasNext())
{
    Object obj = it.next();
    //Do something with obj
}
NemesisX00
la source
12
J'ai l'impression que cela répond plus précisément à la question, car c'est un exemple d'itérateur au lieu d'une solution alternative.
classe
1
Merci pour votre réponse perspicace. pour (...) l'itération est généralement la meilleure solution, mais pas toujours. Aujourd'hui, il se trouve que je recherche une syntaxe d'itérateur explicitement gérée et la voici.
Robert Altman
37
List<String> arrayList = new ArrayList<String>();
for (String s : arrayList) {
    if(s.equals(value)){
        //do something
    }
}

ou

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

Mais attention, ArrayList peut contenir des valeurs nulles . La comparaison devrait donc être

value.equals(arrayList.get(i))

lorsque vous êtes sûr que la valeur n'est pas nulle ou que vous devez vérifier si l'élément donné est nul.

Zacheusz
la source
10

Vous pouvez également utiliser comme ceci:

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

C'est une bonne pratique de lancer et d'utiliser l'objet. Par exemple, si le 'arrayList' contient une liste d'objets 'Object1'. Ensuite, nous pouvons réécrire le code comme suit:

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

Vous pouvez également faire une boucle for comme vous le feriez pour un tableau, mais au lieu de array [i], vous utiliseriez list.get (i)

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

Hormis la réponse de larsmans (qui est en effet correcte), l'exception dans un appel à une méthode get (), donc le code que vous avez posté n'est pas celui qui cause l'erreur.

SJuan76
la source
4

Moyen efficace d'itérer votre ArrayListsuivi de ce lien . Ce type améliorera les performances de la boucle pendant l'itération

int size = list.size();

for(int j = 0; j < size; j++) {
    System.out.println(list.get(i));
}
Crâne Rouge
la source
2

itérer à l'aide de l'itérateur n'est pas sécurisé. Par exemple, si vous ajoutez un élément à la collection après la création de l'itérateur, il lèvera une exception concurrentmodificaionexception. De plus, ce n'est pas thread-safe, vous devez le rendre thread-safe en externe.

Il est donc préférable d'utiliser pour chaque structure de boucle for. C'est au moins à sécurité intégrée.

Sumit Kumar Saha
la source