ArrayList yineleyicisini kullanırken ArrayIndexOutOfBoundsException


103

Şu anda, şuna benzeyen bir kod parçası içeren bir programım var:

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

ArrayList'te yinelemeye kadar bunu doğru yapıyor muyum?

Aldığım hata:

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)

Kodun geri kalanını gösterirdim, ancak oldukça kapsamlı ve yinelemeyi doğru yapmazsam, tek olasılığın ArrayListdoğru şekilde başlatmadığım olduğunu varsayabilirim .


Java 8'de şu forEachyöntemi kullanabilirsiniz : stackoverflow.com/questions/16635398/…
Vitalii Fedorenko

Yanıtlar:


229

Dizi Listesinde yinelemeye kadar bunu doğru yapıyor muyum?

Hayır: iteratorher yinelemede iki kez arayarak , her zaman yeni yineleyiciler alıyorsunuz.

Bu döngüyü yazmanın en kolay yolu, her bir yapı için kullanmaktır :

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

Gelince

java.lang.ArrayIndexOutOfBoundsException: -1

-1Bir diziden eleman numarasını almaya çalıştınız . Sayma sıfırdan başlar.


1
Her biri için kullanın, çok daha kolay. Ayrıca arrayList.iterator (). Next () 'i tekrar çağırıp girdileri atlamış olmanız da mümkündür.

@ larsmans Ah çok teşekkür ederim. Bunu array List ile yapabileceğinizi tamamen unutmuşum. Ancak bunu kodumla denedim ve hala aynı hatayı alıyorum. Bu yüzden, kodda daha önceki diziListesi'ne nasıl eklediğimle ilgili bir sorun olduğunu düşünüyorum, bu yüzden şimdi bu adrese bakacağım. Yine de bunu hatırlattığın için çok teşekkür ederim.
This 0ne Pr0grammer

bunu her operatör için seviyorum. Yakutta her zaman buna benzer bir şey kullanırım ... do array.each |s| unless (s.nil?) end end
David West

2
Sadece not etmek gerekirse, Have you heard ofbiraz saldırgan görünüyor (sebepsiz), ama ben yerli değilim. Aksi takdirde harika.
n611x007

3
@naxa: küçümseyici olarak gelebilir, ifadeyi değiştirdim.
Fred Foo

142

Kabul edilen cevabın genellikle en iyi çözüm olduğunu ve kesinlikle kullanımı daha kolay olduğunu kabul etsem de, hiç kimsenin yineleyicinin doğru kullanımını göstermediğini fark ettim. İşte hızlı bir örnek:

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

12
Alternatif bir çözüm yerine yineleyici bir örnek olduğu için bunun soruyu daha doğru yanıtladığını düşünüyorum.
sınıfsız

1
Anlayışlı yanıtınız için teşekkür ederiz. (...) için yineleme genellikle en iyi çözümdür, ancak her zaman değil. Bugün, açıkça yönetilen yineleyici sözdizimi arıyorum ve işte burada.
Robert Altman

37
List<String> arrayList = new ArrayList<String>();
for (String s : arrayList) {
    if(s.equals(value)){
        //do something
    }
}

veya

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

Ancak dikkatli olun ArrayList boş değerler tutabilir . Öyleyse karşılaştırma olmalı

value.equals(arrayList.get(i))

değerin boş olmadığından eminseniz veya verilen elemanın boş olup olmadığını kontrol etmelisiniz.


10

Ayrıca şu şekilde kullanabilirsiniz:

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

Nesneyi yayınlamak ve kullanmak iyi bir uygulamadır. Örneğin, 'diziListesi' 'Nesne1' nesnelerinin bir listesini içeriyorsa. Ardından kodu şu şekilde yeniden yazabiliriz:

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

8

Bir dizi için yaptığınız gibi bir for döngüsü de yapabilirsiniz, ancak dizi [i] yerine list.get (i) kullanırsınız.

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

7

Larsmans cevabının yanı sıra (gerçekten doğru olan), get () yöntemine yapılan bir çağrıdaki istisna, yani gönderdiğiniz kod hataya neden olan kod değildir.


4

ArrayListBu bağlantıyı takip ederek yinelemenin etkili yolu . Bu tür, yineleme sırasında döngü performansını artıracaktır

int size = list.size();

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

2

Yineleyici kullanarak yineleme, hata güvenli değildir, örneğin yineleyici oluşturulduktan sonra koleksiyona öğe eklerseniz, eşzamanlı değişiklik istisnası oluşturur. Ayrıca iş parçacığı için güvenli değildir, dışarıdan iş parçacığını güvenli hale getirmelisiniz.

Bu nedenle, for döngüsünün her yapısı için kullanmak daha iyidir. En azından güvenli.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.