Reputation: 115
I have ArrayList of lines from file. File contains lines with 5 numbers:
1 1 13 25 25
25 25 11 3 1
25 25 13 1 1
And I have function test(String) to test if I need this line or if I have to remove it from list. My test method:
static boolean test(String s){
return list.contains(reverse(s));
}
reverse(String) returns line with numbers written in reverse order.
For 1 1 13 25 25
it will return 25 25 13 1 1
.
So, I wrote code that uses Iterator to loop through list and remove elements.
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
if(test(iter.next()))
iter.remove();
}
This code works correctly. But IDEA says that the loop can be replaced with Collection.removeIf call. So, I tried to replace code above with this line:
list.removeIf(s->test(s));
But it gives me empty list. Why? What is the difference?
Also I tried to remove lines that contains certain characters using removeIf and it works correctly. Here you can see all program : http://pastebin.com/bWw3cBXg.
My file http://pastebin.com/mEb5sBBJ(~17000 lines)
Upvotes: 3
Views: 1740
Reputation: 691775
You're iterating through the list (by calling contains()
on it) while modifying it, which is generally a bad idea.
Your first algorithm tests if the first line, reversed, is contained in the list. It removes that line. Then it inspects the second (now first) line, and doesn't find a reversed line element, since the first one has already been removed.
The second algorithm is different: it iterates through the list and marks all the indices that must be removed. Then it removes all of them. The second line is the same as the first line reversed. Same for the third. So in the end, everything is reversed.
Although this behavior is not documented in removeIf, it complies with the general contract that predicates should be idempotent, which is not the case here. Calling the predicate on an element of the list doesn't return the same value depending on whether you already have removed another element of the list or not.
Upvotes: 5