java удаление - ArrayIndexOutOfBoundsException при использовании итератора ArrayList





из обратный (8)


Эффективный способ повторить ваш ArrayList за которым следует эта link . Этот тип улучшит производительность цикла во время итерации

int size = list.size();

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

Прямо сейчас у меня есть программа, содержащая фрагмент кода, который выглядит так:

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 должным образом.




Помимо larsmans отвечают (кто действительно прав), исключение в вызове метода get (), поэтому код, который вы отправили, не является тем, который вызывает ошибку.




Вы также можете использовать следующее:

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
}



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 может содержать нулевые значения . Поэтому сравнение должно быть

value.equals(arrayList.get(i))

когда вы уверены, что значение не является нулевым, или вы должны проверить, имеет ли данный элемент значение null.




итерация с использованием итератора не является отказоустойчивой, например, если вы добавляете элемент в коллекцию после создания итератора, то он будет вызывать одновременное исключение. Кроме того, он не является потокобезопасным, вы должны сделать его потоком безопасным извне.

Поэтому лучше использовать для каждой структуры цикла for. Это по крайней мере безотказно.




Хотя я согласен с тем, что принятый ответ обычно является лучшим решением и определенно проще в использовании, я заметил, что никто не показал правильное использование итератора. Итак, вот краткий пример:

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



Вы также можете сделать цикл for, как и для массива, но вместо массива [i] вы должны использовать list.get (i)

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



Извлечение из ссылки Как перебирать карту в Java :

Существует несколько способов итерации по Map на Java. Давайте рассмотрим наиболее распространенные методы и рассмотрим их преимущества и недостатки. Поскольку все карты в Java реализуют интерфейс Map, следующие методы будут работать для любой реализации карты ( HashMap , TreeMap , LinkedHashMap , Hashtable и т. Д.),

Метод №1 : Итерирование записей с использованием цикла For-Each.

Это наиболее распространенный метод и предпочтительнее в большинстве случаев. Он должен использоваться, если вам нужны как ключи карты, так и значения в цикле.

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}

Обратите внимание, что цикл For-Every был введен в Java 5, поэтому этот метод работает только в более новых версиях языка. Также цикл For-Each будет генерировать NullPointerException если вы попытаетесь выполнить итерацию по карте, которая равна null, поэтому перед итерацией вы всегда должны проверять наличие нулевых ссылок.

Метод №2 : Итерирование по клавишам или значениям с использованием цикла For-Each.

Если вам нужны только ключи или значения на карте, вы можете выполнять итерацию по keySet или значениям вместо entrySet.

Map<Integer, Integer> map = new HashMap<Integer, Integer>();

// Iterating over keys only
for (Integer key : map.keySet()) {
    System.out.println("Key = " + key);
}

// Iterating over values only
for (Integer value : map.values()) {
    System.out.println("Value = " + value);
}

Этот метод дает небольшое преимущество в производительности перед итерацией entrySet (примерно на 10% быстрее) и является более чистым.

Метод № 3 : Итерация с использованием Итератора.

Использование дженериков:

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry<Integer, Integer> entry = entries.next();
    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}

Без дженериков:

Map map = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
    Map.Entry entry = (Map.Entry) entries.next();
    Integer key = (Integer)entry.getKey();
    Integer value = (Integer)entry.getValue();
    System.out.println("Key = " + key + ", Value = " + value);
}

Вы также можете использовать один и тот же метод для итерации по keySet или значениям.

Этот метод может выглядеть излишним, но он имеет свои преимущества. Прежде всего, это единственный способ перебора карты в более старых версиях Java. Другая важная особенность заключается в том, что это единственный метод, который позволяет удалять записи с карты во время итерации, вызывая iterator.remove() . Если вы попытаетесь сделать это во время каждой итерации, вы получите «непредсказуемые результаты» в соответствии с Javadoc .

С точки зрения производительности этот метод равен Итерации For-Each.

Метод №4 : Итерация по клавишам и поиск значений (неэффективные).

Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer key : map.keySet()) {
    Integer value = map.get(key);
    System.out.println("Key = " + key + ", Value = " + value);
}

Это может выглядеть как более чистая альтернатива для метода №1, но на практике это довольно медленно и неэффективно, так как получение значений с помощью ключа может занять много времени (этот метод в разных реализациях Map на 20% -200% медленнее, чем метод # 1 ). Если у вас установлен FindBugs, он обнаружит это и предупредит вас о неэффективной итерации. Этот метод следует избегать.

Заключение:

Если вам нужны только ключи или значения с карты, используйте метод # 2. Если вы застряли со старой версией Java (менее 5) или планируете удалять записи во время итерации, вы должны использовать метод # 3. В противном случае используйте метод # 1.







java arraylist iterator indexoutofboundsexception