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.