When you're using an index to iterate through a list, and you're removing items from the list, you need to be careful about how you handle the index. (Doing the remove
through the iterator as in @dasblinkenlight's answer is better in this case, but there are other similar situations where it's not possible.)
Suppose you just deleted the line that resets 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?
}
}
Now, when i==2
, you decide you need to remove the element. When you do so, the item that was element 3 then becomes element 2, and the element that was element 4 then becomes element 3, and so on.
But then you go back up to the top and increment i
. It is now 3. The result is that the element that was element 3, but is now element 2, is never examined at all. It gets skipped.
There are a couple ways to deal with this.
One is to make sure i
doesn't get incremented. I've seen good programmers do things like this:
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
}
}
Personally, I dislike modifying an index inside a for
loop like this, so I'd be happier with
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++;
}
}
[Note that in both cases, it's important to use list.size()
in the termination condition, and not save the original value in a variable. The list size will change, and you want to use the new size when checking for termination.]
Another solution that may be appropriate in some cases is to go backward through the list:
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);
}
}
which doesn't have the problem when elements are shifted.