Обратная итерация через ArrayList дает IndexOutOfBoundsException
Вопрос
Когда я перебираю ArrayList, я получаю исключение IndexOutOfBoundsException.Я попробовал выполнить прямую итерацию, и проблем не возникло.Я ожидаю и знаю, что в списке пять элементов.Код ниже:
Collection rtns = absRtnMap.values();
List list = new ArrayList(rtns);
Collections.sort(list);
for(int j=list.size();j>0;j=j-1){
System.out.println(list.get(j));
}
Прямая итерация - которая работает нормально, но для меня бесполезна:
for(int j=0;j<list.size();j++){
System.out.println(list.isEmpty());
System.out.println(list.get(j));
} // this worked fine
Ошибка:
Exception in thread "Timer-0" java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
at java.util.ArrayList.RangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at model.Return.getReturnMap(Return.java:61)
at controller.Poller$1.run(Poller.java:29)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
Кроме того, если кто-нибудь знает лучшую идиому для обратной итерации, я был бы рад ее попробовать.
Решение
Начните итерацию с list.size() - 1
потому что массив (или ArrayList
) элементы нумеруются от 0 до 1 меньше размера списка.Это довольно стандартная идиома:
for (int j = list.size() - 1; j >= 0; j--) {
// whatever
}
Обратите внимание, что ваша прямая итерация работает, потому что она останавливается до достижение list.size()
.
Другие советы
Избегать индексов вообще?Как насчет:
for (ListIterator iterator = list.listIterator(list.size()); iterator.hasPrevious();) {
final Object listElement = iterator.previous();
}
Я знаю, что это старый вопрос, но Java содержит Collections.reverse( List<T> )
метод.Почему бы вам просто не перевернуть его и не выполнить прямую итерацию?
Самый элегантный способ — перевернуть массив и затем использовать прямой (или даже неявный) итератор:
Collections.reverse(arrayList);
for (Object item : arrayList) {
...
}
List.size() превышает последний допустимый индекс.
for(int j = list.size() - 1; j >= 0; j--) {
System.out.println(list.get(j));
}
Массивы Java имеют нулевой индекс.Вам нужно будет установить j = list.size() - 1 и продолжать до тех пор, пока j = 0.
Если списки довольно малы и производительность не является реальной проблемой, можно использовать reverse
-метод Lists
-класс в Google Guava
.Урожайность довольно for-each
-code, и исходный список останется прежним.Кроме того, перевернутый список поддерживается исходным списком, поэтому любые изменения в исходном списке будут отражены в перевернутом списке.
import com.google.common.collect.Lists;
[...]
final List<String> myList = Lists.newArrayList("one", "two", "three");
final List<String> myReverseList = Lists.reverse(myList);
System.out.println(myList);
System.out.println(myReverseList);
myList.add("four");
System.out.println(myList);
System.out.println(myReverseList);
Дает следующий результат:
[one, two, three]
[three, two, one]
[one, two, three, four]
[four, three, two, one]
Это означает, что обратную итерацию myList можно записать так:
for (final String someString : Lists.reverse(myList) {
//do something
}
Вы можете отменить одну строку, которая
Коллекции.обратный(список);
ArrayList arrayList = new ArrayList();
arrayList.add("A");
arrayList.add("B");
System.out.println("Before Reverse Order : " + arrayList);
Collections.reverse(arrayList);
System.out.println("After Reverse : " + arrayList);
Выход
Before Reverse Order : [A, B]
After Reverse : [B, A]
Вы можете сделать это, если вам удобен цикл foreach.
List<String> list = new ArrayList<String>();
list.add("ABC");
list.add("DEF");
list.add("GHI");
ListIterator<String> listIterator = list.listIterator(list.size());
while(listIterator.hasPrevious()){
System.out.println(listIterator.previous());
}