2011-07-14 16 views
102

Teraz mam program zawierający fragment kodu, który wygląda tak:ArrayIndexOutOfBoundsException przy użyciu ArrayList jest iterator

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

robię to prawo, o ile iteracja ArrayList idzie?

Błąd otrzymuję to:

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) 

chciałbym pokazać resztę kodu, ale jest to dość obszerna, a jeśli nie mam właściwie robić iteracji, chciałbym założyć, jedyną możliwością jest to, że Nie zainicjalizuję poprawnie ArrayList.

+0

W java 8 możesz użyć metody 'forEach': http://stackoverflow.com/questions/16635398/java-8-iterable-foreach-vs-foreach-loop –

Odpowiedz

228
Czy robię to dobrze, o ile chodzi o powtarzanie przez tablicę?

Nie: dzwoniąc pod numer iterator dwa razy w każdej iteracji, cały czas otrzymujesz nowe iteratory.

Najłatwiej napisać pętlę używa for-each konstrukt:

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

jak dla

java.lang.ArrayIndexOutOfBoundsException: -1

Po prostu starał się elementu numer -1 z tablicy . Liczenie rozpoczyna się od zera.

+1

Używaj dla każdego, jest to znacznie łatwiejsze. Możliwe też, że znowu wywołałeś arrayList.iterator(). Next() i pominąłeś wpisy. –

+0

@ larsmans Ah dziękuję bardzo. Całkowicie zapomniałem, że możesz to zrobić z listą tablic. Jednak próbowałem tego z moim kodem i nadal otrzymuję ten sam błąd. Więc myślę, że to jest problem z tym, jak dodaje się do tablicy LIST wcześniej w kodzie, więc teraz spojrzę na ten adres. Mimo to, dziękuję bardzo za przypomnienie mi o tym. –

+0

Uwielbiam to dla każdego operatora. Używam czegoś takiego w Ruby przez cały czas ... 'do array.each | s | , chyba że (s.nil?) koniec koniec' –

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

lub

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

Ale bądź ostrożny ArrayList może posiadać wartości null. Tak więc porównanie powinno być

value.equals(arrayList.get(i)) 

gdy jesteś pewien, że wartość nie jest zerowa lub powinieneś sprawdzić, czy dany element ma wartość null.

+0

Dziękuję za twój wkład. :) –

7

Oprócz odpowiedzi larsmans (kto jest rzeczywiście poprawny), wyjątek w wywołaniu metody get(), więc kod, który wysłałeś, nie jest tym, który powoduje błąd.

8

Można również zrobić dla pętli jak dla tablicy, ale zamiast array [i] należałoby użyć list.get (i)

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

Chociaż zgadzam się, że przyjęte rozwiązanie jest zazwyczaj najlepsze rozwiązanie i zdecydowanie łatwiejsze w obsłudze, zauważyłem, że nikt nie wyświetla poprawnego użycia iteratora. Więc tutaj jest krótki przykład:

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

Czuję, że to dokładniej odpowiada na pytanie, ponieważ jest to przykład iteracyjny zamiast alternatywnego rozwiązania. – withoutclass

+1

Dziękuję za twoją wnikliwą odpowiedź. dla (...) iteracja jest * zwykle * najlepszym rozwiązaniem, ale nie zawsze. Dzisiaj zdarza mi się, że szukam jawnie zarządzanej składni iteracyjnej i oto ona. –

+1

piękna i przydatna odpowiedź. – Fattie

10

Można również użyć tak:

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

Jest to dobra praktyka, aby rzucić i korzystania z obiektu. Na przykład, jeśli 'arrayList' zawiera listę obiektów 'Object1'.Wtedy możemy ponownie napisać kod jako:

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

skutecznym sposobem iteracyjne swój ArrayList następnie ten link. Ten typ będzie poprawić wydajność podczas iteracji pętli

int size = list.size(); 

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

iteracji za pomocą iteratora nie jest fail-safe na przykład jeśli dodać element do kolekcji po utworzeniu iteratora to będzie rzucać concurrentmodificaionexception. Ponadto nie jest bezpieczny dla wątków, musisz nosić go bezpiecznie na zewnątrz.

Lepiej więc użyć dla każdej struktury pętli for. Jest przynajmniej bezpieczny w razie awarii.

Powiązane problemy