web-dev-qa-db-ja.com

ArrayListのイテレータを使用している場合のArrayIndexOutOfBoundsException

今、私はこのようなコードの一部を含むプログラムを持っています。

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

ArrayListを繰り返し処理するという点では、そうしていますか。

私が得ているエラーは次のとおりです。

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)

残りのコードを表示しますが、かなり広範囲にわたるので、反復を正しく実行していない場合は、ArrayListを正しく初期化していないことが唯一の可能性と考えます。

102

私はそのようにしているのですか。

いいえ:各反復でiteratorを2回呼び出すことで、常に新しい反復子が得られます。

このループを書く最も簡単な方法は、 for-each 構文を使うことです。

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

はどうかと言うと

Java.lang.ArrayIndexOutOfBoundsException: -1

配列から要素番号-1を取得しようとしました。カウントはゼロから始まります。

228
Fred Foo

私は、受け入れられた答えが通常最善の解決策であり、間違いなく使いやすいことに同意しますが、私は誰もイテレータの正しい使い方を表示していないことに気づきました。簡単な例です。

Iterator<Object> it = arrayList.iterator();
while(it.hasNext())
{
    Object obj = it.next();
    //Do something with obj
}
141
NemesisX00
List<String> arrayList = new ArrayList<String>();
for (String s : arrayList) {
    if(s.equals(value)){
        //do something
    }
}

または

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

しかし注意してくださいArrayListはnull値を保持できます。したがって、比較は

value.equals(arrayList.get(i))

値がnullではないことが確実な場合、または指定された要素がnullかどうかを確認する必要がある場合.

37
zacheusz

このように使うこともできます。

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

オブジェクトをキャストして使用するのは良い習慣です。たとえば、「arrayList」に「Object1」オブジェクトのリストが含まれているとします。それから、コードを次のように書き直すことができます。

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

配列と同じようにforループを実行することもできますが、array [i]の代わりにlist.get(i)を使用します。

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

Larsmansの回答(確かに正しい人)は別として、get()メソッドの呼び出しの例外なので、あなたが投稿したコードはエラーの原因となっているものではありません。

7
SJuan76

この後に続くArrayListを反復する効率的な方法 link 。このタイプは、反復中のループのパフォーマンスを向上させます

int size = list.size();

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

イテレータを使用してイテレートすることは、たとえばイテレータの作成後にコレクションに要素を追加した場合、フェイルセーフではありません。そうすると、同時変更例外が発生します。また、スレッドセーフではありません。外部でスレッドセーフにする必要があります。

そのため、forループのfor-each構造を使用する方が適切です。少なくともフェイルセーフです。

2