Когда вы используете индекс для итерации по списку, и вы удаляете элементы из списка, вам нужно быть осторожным в том, как вы обрабатываете индекс. (. Выполнение remove
через итератор, как в @ ответ dasblinkenlight является лучше в этом случае, но есть и другие подобные ситуации, когда это не представляется возможным)
Предположим, вы только что удалили строку, которая сбрасывает i
:
for (int i = 0; i < list.size(); i++) {
String dateNoTime = list.get(i).split(" ")[0];
System.out.println(" Going over : "+list.get(i));
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+list.get(i));
list.remove(i);
//i = -1; //This is making the loop start from scratch. Is there a better way?
}
}
Теперь, когда i==2
, вы решили, что вам нужно удалить элемент. Когда вы это сделаете, элемент, который был элементом 3, затем становится элементом 2, а элемент, который был элементом 4, становится элементом 3 и т. Д.
Но, тогда вы возвращаетесь наверх и увеличиваете i
. Это сейчас 3. В результате элемент, который был элемент 3, но теперь элемент 2, никогда не рассматривается вообще. Он пропускается.
Есть несколько способов справиться с этим.
Нужно убедиться, что i
не увеличивается.Я видел хорошие программисты делают такие вещи, как это:
for (int i = 0; i < list.size(); i++) {
String dateNoTime = list.get(i).split(" ")[0];
System.out.println(" Going over : "+list.get(i));
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+list.get(i));
list.remove(i);
i--; // Move "i" backwards so that no elements are skipped
}
}
Лично я не люблю изменение индекса внутри for
цикла, как это, так что я был бы счастлив с
int i = 0;
while (i < list.size()) {
String dateNoTime = list.get(i).split(" ")[0];
System.out.println(" Going over : "+list.get(i));
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+list.get(i));
list.remove(i);
} else {
i++;
}
}
[Обратите внимание, что в оба случая, важно использовать list.size()
в состоянии завершения и не сохранять исходное значение в переменной. . Размер списка изменится, и вы хотите использовать новый размер при проверке окончания]
Другое решение, которое может быть уместным в некоторых случаях идти назад по списку:
for (int i = list.size() - 1; i >= 0; i--)
String dateNoTime = list.get(i).split(" ")[0];
System.out.println(" Going over : "+list.get(i));
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+list.get(i));
list.remove(i);
}
}
который Безразлично У меня проблема, когда элементы смещены.
Я что-то упустил? почему вы не можете просто удалить часть 'i = -1'? – SOfanatic
Должно быть исключение параллельной модификации !? Вместо этого используйте Итератор. –
только петля в обратном направлении. (от конца до начала) – njzk2