ArrayIndexOutOfBoundsException khi sử dụng trình lặp của ArrayList


103

Ngay bây giờ, tôi có một chương trình chứa một đoạn mã trông giống như sau:

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

Tôi làm vậy có đúng không, cho đến khi lặp qua ArrayList?

Lỗi tôi nhận được là:

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)

Tôi sẽ hiển thị phần còn lại của mã, nhưng nó khá rộng và nếu tôi không thực hiện lặp lại chính xác, tôi sẽ cho rằng khả năng duy nhất là tôi không khởi tạo ArrayListđúng cách.


Trong java 8, bạn có thể sử dụng forEachphương thức: stackoverflow.com/questions/16635398/…
Vitalii Fedorenko

Câu trả lời:


229

Tôi làm vậy có đúng không, cho đến khi lặp lại qua Arraylist?

Không: bằng cách gọi iteratorhai lần trong mỗi lần lặp, bạn luôn nhận được các trình lặp mới.

Cách dễ nhất để viết vòng lặp này là sử dụng cấu trúc for-each :

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

Đối với

java.lang.ArrayIndexOutOfBoundsException: -1

Bạn vừa cố gắng lấy số phần tử -1từ một mảng. Việc đếm bắt đầu từ số không.


1
Sử dụng cho từng thứ, nó dễ dàng hơn nhiều. Ngoài ra, có thể bạn đã gọi lại arrayList.iterator (). Next () và bỏ qua các mục nhập.

@ larsmans Ah cảm ơn bạn nhiều. Tôi hoàn toàn quên rằng bạn có thể làm điều đó với Danh sách mảng. Tuy nhiên, tôi đã thử điều đó với mã của mình và tôi vẫn gặp lỗi tương tự. Vì vậy, tôi nghĩ rằng đó là một vấn đề với cách tôi thêm vào arrayList trước đó trong mã, vì vậy bây giờ tôi sẽ xem xét địa chỉ đó. Tuy nhiên, cảm ơn bạn rất nhiều vì đã nhắc nhở tôi về điều đó.
This 0ne Pr0grammer

tình yêu đó cho mỗi nhà điều hành. Tôi sử dụng một cái gì đó giống như nó trong ruby tất cả thời gian ... do array.each |s| unless (s.nil?) end end
David West

2
Chỉ cần lưu ý, Have you heard ofcó vẻ hơi khó chịu (không có lý do), nhưng tôi không phải là người bản xứ. Nếu không thì tuyệt.
n611x007 9/12/12

3
@naxa: nó có thể trở nên trịch thượng, tôi đã thay đổi từ ngữ.
Fred Foo

142

Mặc dù tôi đồng ý rằng câu trả lời được chấp nhận thường là giải pháp tốt nhất và chắc chắn dễ sử dụng hơn, nhưng tôi nhận thấy không ai hiển thị cách sử dụng trình lặp thích hợp. Đây là một ví dụ nhanh:

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

12
Tôi cảm thấy như điều này trả lời chính xác hơn câu hỏi, vì đó là một ví dụ về trình lặp thay vì một giải pháp thay thế.
withoutclass

1
Cảm ơn bạn đã trả lời sâu sắc của bạn. lặp lại for (...) thường là giải pháp tốt nhất, nhưng không phải lúc nào cũng vậy. Hôm nay, tôi tình cờ tìm kiếm cú pháp trình lặp được quản lý rõ ràng và nó đây.
Robert Altman

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

hoặc là

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

Nhưng hãy cẩn thận ArrayList có thể chứa các giá trị null . Vì vậy, so sánh nên

value.equals(arrayList.get(i))

khi bạn chắc chắn rằng giá trị đó không phải là null hoặc bạn nên kiểm tra xem phần tử đã cho có là null hay không.


10

Bạn cũng có thể sử dụng như thế này:

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

Đó là một thực hành tốt để truyền và sử dụng đối tượng. Ví dụ: nếu 'arrayList' chứa danh sách các đối tượng 'Object1'. Sau đó, chúng ta có thể viết lại mã dưới dạng:

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

8

Bạn cũng có thể thực hiện một vòng lặp for như bạn làm với một mảng nhưng thay vì mảng [i], bạn sẽ sử dụng list.get (i)

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

7

Ngoài câu trả lời larsmans (ai thực sự đúng), ngoại lệ trong lệnh gọi phương thức get (), vì vậy mã bạn đã đăng không phải là mã gây ra lỗi.


4

Cách hiệu quả để lặp lại ArrayListtheo dõi của bạn bằng liên kết này . Loại này sẽ cải thiện hiệu suất của vòng lặp trong quá trình lặp lại

int size = list.size();

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

2

lặp lại bằng cách sử dụng trình lặp là không an toàn, ví dụ: nếu bạn thêm phần tử vào bộ sưu tập sau khi tạo trình lặp thì nó sẽ ném ra đồng thờimodificaionexception. Ngoài ra, nó không an toàn cho chủ đề, bạn phải làm cho nó an toàn bên ngoài.

Vì vậy, tốt hơn là sử dụng cấu trúc for-each của vòng lặp for. Nó ít nhất là không an toàn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.