ArrayIndexOutOfBoundsException เมื่อใช้ตัววนซ้ำของ ArrayList


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 คุณสามารถใช้forEachmethod: stackoverflow.com/questions/16635398/…
Vitalii Fedorenko

คำตอบ:


229

ฉันทำถูกต้องหรือไม่เท่าที่ทำซ้ำผ่าน Arraylist ไป

ไม่: การโทรiteratorสองครั้งในการทำซ้ำแต่ละครั้งคุณจะได้รับตัวทำซ้ำใหม่ตลอดเวลา

วิธีที่ง่ายที่สุดในการเขียนลูปนี้คือการใช้โครงสร้างสำหรับแต่ละตัว :

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

ส่วน

java.lang.ArrayIndexOutOfBoundsException: -1

คุณเพิ่งพยายามรับหมายเลของค์ประกอบ-1จากอาร์เรย์ การนับเริ่มต้นที่ศูนย์


1
ใช้สำหรับแต่ละคนง่ายกว่ามาก นอกจากนี้ยังเป็นไปได้ที่คุณจะเรียกว่า arrayList.iterator () next () อีกครั้งและข้ามรายการ

@ larsmans อ่าขอบคุณมาก ฉันลืมไปเลยว่าคุณสามารถทำได้ด้วยรายการอาร์เรย์ อย่างไรก็ตามฉันได้ลองใช้รหัสแล้วและยังคงได้รับข้อผิดพลาดเดิม ดังนั้นฉันคิดว่ามันเป็นปัญหากับวิธีที่ฉันเพิ่มลงใน arrayList ก่อนหน้านี้ในโค้ดดังนั้นตอนนี้ฉันจะดูที่อยู่นั้น ยังไงก็ขอบคุณมากที่เตือนฉันเรื่องนั้น
0ne Pr0grammer นี้

ชอบสิ่งนั้นสำหรับผู้ปฏิบัติงานแต่ละคน ฉันใช้บางอย่างในทับทิมตลอดเวลา ... do array.each |s| unless (s.nil?) end end
David West

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
ฉันรู้สึกว่าสิ่งนี้ตอบคำถามได้ถูกต้องมากขึ้นเนื่องจากเป็นตัวอย่างตัววนซ้ำแทนที่จะเป็นทางเลือกอื่น
คลาส

1
ขอบคุณสำหรับคำตอบที่ชาญฉลาด สำหรับ (... ) การวนซ้ำมักจะเป็นทางออกที่ดีที่สุด แต่ก็ไม่เสมอไป วันนี้ฉันกำลังมองหาไวยากรณ์ตัวทำซ้ำที่มีการจัดการอย่างชัดเจนและนี่คือ
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))

เมื่อคุณแน่ใจว่าค่านั้นไม่เป็นโมฆะหรือคุณควรตรวจสอบว่าองค์ประกอบที่กำหนดเป็นโมฆะหรือไม่


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 loop ได้เหมือนที่คุณต้องการสำหรับอาร์เรย์ แต่แทนที่จะใช้อาร์เรย์ [i] คุณจะใช้ list.get (i)

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

7

นอกเหนือจากคำตอบของ larsmans (ใครถูกต้อง) ข้อยกเว้นในการเรียกใช้เมธอด get () ดังนั้นรหัสที่คุณโพสต์จึงไม่ใช่รหัสที่ทำให้เกิดข้อผิดพลาด


4

วิธีที่มีประสิทธิภาพในการทำซ้ำArrayListตามลิงค์นี้ ประเภทนี้จะปรับปรุงประสิทธิภาพของการวนซ้ำระหว่างการวนซ้ำ

int size = list.size();

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

2

การทำซ้ำโดยใช้ iterator ไม่ใช่ข้อผิดพลาดตัวอย่างเช่นหากคุณเพิ่มองค์ประกอบในคอลเลกชันหลังจากการสร้างตัววนซ้ำมันจะโยนข้อผิดพลาดที่เกิดขึ้นพร้อมกัน นอกจากนี้ยังไม่ปลอดภัยคุณต้องทำให้ด้ายปลอดภัยจากภายนอก

ดังนั้นจึงเป็นการดีกว่าที่จะใช้สำหรับแต่ละโครงสร้างของ for loop มันปลอดภัยอย่างน้อยที่สุด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.