ArrayListの反復子を使用すると、ArrayIndexOutOfBoundsException


103

現在、次のようなコードを含むプログラムがあります。

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適切に初期化していないことが唯一の可能性であると想定します。


Javaの8では、あなたは使用することができますforEach:メソッドstackoverflow.com/questions/16635398/...
Vitalii Fedorenko

回答:


229

Arraylistを反復処理する限り、私はそれを正しく行っていますか?

いいえ:iterator各反復で2回呼び出すことにより、常に新しいイテレーターを取得します。

このループを記述する最も簡単な方法は、for-each構文を使用することです

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

はどうかと言うと

java.lang.ArrayIndexOutOfBoundsException: -1

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


1
for-eachを使用すると、はるかに簡単です。また、arrayList.iterator()。next()を再度呼び出してエントリをスキップした可能性もあります。

@larsmansああ、どうもありがとうございました。あなたが配列リストでそれをすることができることを完全に忘れました。しかし、私は自分のコードでそれを試しましたが、それでも同じエラーが発生します。コードの前半でarrayListにどのように追加するかが問題だと思うので、それについて説明します。それでも、それを思い出させてくれて本当にありがとう。
この0ne Pr0grammer

各オペレーターにとってそれが大好きです。私はいつもルビーでそのようなものを使用しています... do array.each |s| unless (s.nil?) end end
デビッドウェスト

2
注意してください、Have you heard of(理由もなく)一種の攻撃的なようですが、私はネイティブではありません。そうでなければ素晴らしい。
n611x007

3
@naxa:それは侮辱としてやって来るかもしれません、私は言い回しを変更しました。
Fred Foo

142

受け入れられた回答が通常最良の解決策であり、間違いなく使いやすいことに同意しますが、イテレータの適切な使用法を誰も表示していないことに気付きました。だからここに簡単な例があります:

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

12
これは別のソリューションではなくイテレータの例であるため、これはより正確に質問に答えると思います。
クラスなし2013

1
洞察に満ちた回答をありがとうございます。for(...)反復は通常、最良のソリューションですが、常にそうとは限りません。今日、私はたまたま明示的に管理されたイテレータ構文を探していますが、ここにあります。
Robert Altman

37
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かどうかを確認する必要がある場合。


10

次のように使用することもできます:

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
}

8

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

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

7

ラースマンの回答(確かに正しい)とは別に、get()メソッドの呼び出しの例外。そのため、投稿したコードはエラーの原因ではありません。


4

ArrayListこのリンクをたどってあなたをフォローする効率的な方法。このタイプは、反復中のループのパフォーマンスを向上させます

int size = list.size();

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

2

イテレータを使用した反復はフェイルセーフではありません。たとえば、イテレータの作成後に要素をコレクションに追加すると、concurrentmodificaionexceptionがスローされます。また、スレッドセーフではありません。外部でスレッドセーフにする必要があります。

したがって、forループのfor-each構造を使用することをお勧めします。少なくともフェイルセーフです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.