What's the replacement For-Each loop for filtering?
What do you mean by "filtering"? Removing some items from the list? If so, you can use an iterator :
for(Iterator<MyElement> it = list.iterator(); it.hasNext(); ) {
MyElement element = it.next();
if (some condition) {
it.remove();
}
}
Update (based on comments):
Let's look at an example to illustrate how an iterator works. Let's say we have a list containing "A" and "B":
AABBA
We want to remove all these pesky B
s. So, using the above loop, the code would work like this:
- hasNext ()? Yes. following().
element
indicates 1st A. - hasNext ()? Yes. following().
element
points to the second A. - hasNext ()? Yes. following().
element
points to 1st B. remove (). the iterator counter does NOT change, it still points to where B is (technically not entirely correct, but logical that it works). If you must call remove () again, you will get an exception (because the list item no longer exists). - hasNext ()? Yes. following().
element
points to the second B. The rest is the same as # 3 - hasNext ()? Yes. following().
element
indicates the third A. - hasNext ()? No, everything is ready. The list now has 3 items.
Update # 2 : The remove()
operation is indeed required for the iterator, but only because it is optional in the underlying collection. Bottom line here - if your collection supports it (and all collections in the Java Collection Framework do), so would an iterator. If your collection doesn't support it, you're out of luck anyway.
source to share
ChssPly76's answer is the correct approach here, but I'm intrigued with respect to your thinking: "Index traversal is not a good option." In many cases - the general case, in particular the one that has ArrayList
- it is extremely effective. (Actually, in the case of Arraylist, I find that repeated calls are get(i++)
slightly faster than using Iterator, although not close enough to sacrifice readability).
In general, if the object in question implements java.util.RandomAccess , then accessing successive elements through the index should be roughly the same using an Iterator. If this is not the case (for example, LinkedList
would be a good counterexample), then you are correct; but don't turn this option out of control.
source to share
If you, like me, don't like modifying the collection when iterating through the elements, or if the iterator simply doesn't provide an implementation for deletion, you can use a temporary collection to just collect the elements you want to delete.Yes, yes, it's less efficient by compared to modifying the iterator, but it's clearer for me to understand what's going on:
List<Object> data = getListFromSomewhere();
List<Object> filter = new ArrayList<Object>();
// create Filter
for (Object item: data) {
if (throwAway(item)) {
filter.add(item);
}
}
// use Filter
for (Object item:filter) {
data.remove(item);
}
filter.clear();
filter = null;
source to share