ArrayIndexOutOfBoundsException saat menggunakan iterator ArrayList

103

Saat ini, saya memiliki program yang berisi potongan kode yang terlihat seperti ini:

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

Apakah saya melakukan itu dengan benar, sejauh iterasi melalui ArrayList berjalan?

Kesalahan yang saya dapatkan adalah:

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)

Saya akan menunjukkan sisa kode, tetapi itu cukup ekstensif, dan jika saya tidak melakukan iterasi dengan benar, saya akan berasumsi satu-satunya kemungkinan adalah bahwa saya tidak menginisialisasi dengan ArrayListbenar.

Programmer 0ne ini
sumber
Di java 8 Anda dapat menggunakan forEachmetode: stackoverflow.com/questions/16635398/…
Vitalii Fedorenko

Jawaban:

229

Apakah saya melakukan itu dengan benar, sejauh iterasi melalui Arraylist berjalan?

Tidak: dengan memanggil iteratordua kali di setiap iterasi, Anda mendapatkan iterator baru setiap saat.

Cara termudah untuk menulis perulangan ini menggunakan konstruksi for-each :

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

Adapun

java.lang.ArrayIndexOutOfBoundsException: -1

Anda baru saja mencoba mendapatkan nomor elemen -1dari sebuah array. Penghitungan dimulai dari nol.

Fred Foo
sumber
1
Gunakan untuk masing-masing, itu jauh lebih mudah. Juga mungkin Anda memanggil arrayList.iterator (). Next () lagi dan melewatkan entri.
@ larsmans Ah terima kasih banyak. Saya benar-benar lupa Anda bisa melakukan itu dengan Daftar array. Namun, saya mencobanya dengan kode saya, dan saya masih mendapatkan kesalahan yang sama. Jadi saya pikir itu masalah dengan bagaimana saya menambahkan ke arrayList sebelumnya dalam kode, jadi sekarang saya akan melihat alamat itu. Tetap saja, terima kasih banyak telah mengingatkan saya tentang itu.
Programmer 0ne ini
suka itu untuk setiap operator. Saya menggunakan sesuatu seperti itu di ruby ​​sepanjang waktu ... do array.each |s| unless (s.nil?) end end
David West
2
Sekadar catatan, Have you heard ofsepertinya agak menyinggung (tanpa alasan), tapi saya bukan penduduk asli. Jika tidak bagus.
n611x007
3
@naxa: ini mungkin dianggap merendahkan, saya telah mengubah kata-katanya.
Fred Foo
142

Meskipun saya setuju bahwa jawaban yang diterima biasanya merupakan solusi terbaik dan pasti lebih mudah digunakan, saya perhatikan tidak ada yang menunjukkan penggunaan iterator yang tepat. Jadi, inilah contoh singkatnya:

Iterator<Object> it = arrayList.iterator();
while(it.hasNext())
{
    Object obj = it.next();
    //Do something with obj
}
NemesisX00
sumber
12
Saya merasa ini lebih akurat menjawab pertanyaan, karena ini adalah contoh iterator dan bukan solusi alternatif.
kelas
1
Terima kasih atas tanggapan Anda yang berwawasan. untuk (...) iterasi biasanya merupakan solusi terbaik, tetapi tidak selalu. Hari ini, saya kebetulan mencari sintaks iterator yang dikelola secara eksplisit dan ini dia.
Robert Altman
37
List<String> arrayList = new ArrayList<String>();
for (String s : arrayList) {
    if(s.equals(value)){
        //do something
    }
}

atau

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

Tapi hati-hati ArrayList bisa menampung nilai null . Jadi perbandingan seharusnya

value.equals(arrayList.get(i))

ketika Anda yakin bahwa nilainya bukan null atau Anda harus memeriksa apakah elemen yang diberikan adalah null.

zacheusz
sumber
10

Anda juga bisa menggunakan seperti ini:

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

Ini praktik yang baik untuk melemparkan dan menggunakan objek. Misalnya, jika 'arrayList' berisi daftar objek 'Object1'. Kemudian, kita dapat menulis ulang kode tersebut sebagai:

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

Anda juga bisa melakukan perulangan for seperti yang Anda lakukan untuk larik tetapi alih-alih larik [i], Anda akan menggunakan list.get (i)

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

Terlepas dari jawaban larsman (yang memang benar), pengecualian dalam panggilan ke metode get (), jadi kode yang Anda posting bukanlah yang menyebabkan kesalahan.

SJuan76
sumber
4

Cara yang efisien untuk mengulang Anda ArrayListdiikuti oleh tautan ini . Jenis ini akan meningkatkan kinerja perulangan selama iterasi

int size = list.size();

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

iterasi menggunakan iterator tidak aman untuk kegagalan misalnya jika Anda menambahkan elemen ke koleksi setelah pembuatan iterator maka itu akan memunculkan concurrentmodificaionexception. Juga tidak aman untuk benang, Anda harus membuatnya aman untuk benang secara eksternal.

Jadi lebih baik menggunakan untuk-setiap struktur for loop. Ini setidaknya aman dari kegagalan.

Sumit Kumar Saha
sumber