ArrayIndexOutOfBoundsException ao usar o iterador de ArrayList


103

No momento, tenho um programa que contém um trecho de código semelhante a este:

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

Estou fazendo isso certo, no que diz respeito à iteração por meio da ArrayList?

O erro que estou recebendo é:

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)

Eu mostraria o resto do código, mas é bastante extenso e, se não estou fazendo a iteração corretamente, presumo que a única possibilidade é não estar inicializando ArrayListcorretamente.


Em java 8, você pode usar o forEachmétodo: stackoverflow.com/questions/16635398/…
Vitalii Fedorenko

Respostas:


229

Estou fazendo isso certo, no que diz respeito à iteração pelo Arraylist?

Não: chamando iteratorduas vezes em cada iteração, você obtém novos iteradores o tempo todo.

A maneira mais fácil de escrever esse loop é usando a construção for-each :

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

Quanto a

java.lang.ArrayIndexOutOfBoundsException: -1

Você acabou de tentar obter o número -1do elemento de uma matriz. A contagem começa em zero.


1
Use para cada um, é muito mais fácil. Também é possível que você tenha chamado arrayList.iterator (). Next () novamente e pulado as entradas.

@ larsmans Ah, muito obrigado. Eu esqueci totalmente que você poderia fazer isso com o array List. No entanto, tentei fazer isso com meu código e ainda estou recebendo o mesmo erro. Portanto, acho que é um problema de como estou adicionando ao arrayList no início do código, então agora examinarei como resolver isso. Ainda assim, muito obrigado por me lembrar disso.
Este 0ne Pr0grammer

amo isso para cada operador. Eu uso algo assim em ruby ​​o tempo todo ... do array.each |s| unless (s.nil?) end end
David West,

2
Só para notar, Have you heard ofparece meio ofensivo (sem motivo), mas não sou nativo. Caso contrário, ótimo.
n611x007

3
@naxa: pode parecer condescendente, mudei o texto.
Fred Foo

142

Embora eu concorde que a resposta aceita geralmente é a melhor solução e definitivamente mais fácil de usar, percebi que ninguém exibiu o uso adequado do iterador. Então, aqui está um exemplo rápido:

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

12
Acho que isso responde com mais precisão à pergunta, já que é um exemplo de iterador em vez de uma solução alternativa.
aula de

1
Obrigado por sua resposta perspicaz. pois (...) iteração é geralmente a melhor solução, mas nem sempre. Hoje, estou procurando uma sintaxe de iterador explicitamente gerenciada e aqui está.
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
    }
}

Mas tenha cuidado, ArrayList pode conter valores nulos . Portanto, a comparação deve ser

value.equals(arrayList.get(i))

quando tiver certeza de que o valor não é nulo ou você deve verificar se determinado elemento é nulo.


10

Você também pode usar desta forma:

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

É uma boa prática lançar e usar o objeto. Por exemplo, se 'arrayList' contém uma lista de objetos 'Object1'. Então, podemos reescrever o código como:

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

8

Você também pode fazer um loop for como faria para um array, mas em vez de array [i], você usaria list.get (i)

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

7

Além da resposta de larsmans (que de fato está correta), a exceção em uma chamada para um método get (), então o código que você postou não é o que está causando o erro.


4

Maneira eficiente de iterar seu ArrayListseguido por este link . Este tipo irá melhorar o desempenho do loop durante a iteração

int size = list.size();

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

2

iterar usando o iterador não é seguro contra falhas, por exemplo, se você adicionar um elemento à coleção após a criação do iterador, ele lançará concurrentmodificaionexception. Além disso, não é thread-safe, você deve torná-lo thread-safe externamente.

Portanto, é melhor usar for-each estrutura de loop for. É pelo menos à prova de falhas.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.