| Author |
for loop question
|
Warren Bell
Ranch Hand
Joined: Dec 20, 2000
Posts: 55
|
|
What is the correct way to remove an object from a List in a for loop? I have run into problems with the old for loop, not the while loop, doing the same thing. It would cause the loop to loop less missing the last object in the list. Worked around it, but have not tried it with Java5 and was not sure if there was a standard way of doing it. Here are some ways I am thinking of doing it:
for(Object o : listOfObjects)
{
listOfObjects.remove(o);
}
or
int i = 0;
for(Object o : listOfObjects)
{
listOfObjects.remove(i);
i++;
}
And is there some sort of default counter or do you have to do the i++ deal?
Warren Bell
|
 |
Freddy Wong
Ranch Hand
Joined: Sep 11, 2006
Posts: 959
|
|
Don't do that. You can get ConcurrentModificationException if you try to remove an element from a list in an enhanced for loop. Use java.util.Iterator.remove() to safely remove the element while looping, e.g.
Fixed the typo: Sorry, it should be iter.remove() and not list.remove().
|
SCJP 5.0, SCWCD 1.4, SCBCD 1.3, SCDJWS 1.4
My Blog
|
 |
Vijitha Kumara
Bartender
Joined: Mar 24, 2008
Posts: 3670
|
|
Warren Bell wrote: I have run into problems with the old for loop, not the while loop, doing the same thing. It would cause the loop to loop less missing the last object in the list.
Can you show us how ? What you used to iterate the collection ?
|
 |
Rob Spoor
Sheriff
Joined: Oct 27, 2005
Posts: 19216
|
|
First of all, both are a ConcurrentModificationException waiting to happen. You cannot modify most collections while iterating over them, except through the iterator that is used:
ListIterator has similar methods for adding and replacing values.
Now, as for the issue at hand. Consider a list with the following contents: [0, 1, 2, 3, 4, 5]
You then iterate over it, and remove element i
When i == 0, the list will be [1, 2, 3, 4, 5]. You increase i to 1, so the next time you remove element i you will skip the 1: [1, 3, 4, 5]. i will then be 2, and you skip the 3 as well: [1, 3, 5]. i is now 3 so it cannot remove anything.
There are two ways of solving this:
1) whenever you remove something, do not increase i:
If you use a traditional for-loop, you must decrease the counter because it always gets increased:
2) Loop backwards. This will prevent you skipping past elements:
|
SCJP 1.4 - SCJP 6 - SCWCD 5
How To Ask Questions How To Answer Questions
|
 |
salvin francis
Ranch Hand
Joined: Jan 12, 2009
Posts: 915
|
|
|
isnt there a clear method ??
|
My Website: [Salvin.in] Cool your mind:[Salvin.in/painting] My Sally:[Salvin.in/sally]
|
 |
salvin francis
Ranch Hand
Joined: Jan 12, 2009
Posts: 915
|
|
I meant
|
 |
Rob Spoor
Sheriff
Joined: Oct 27, 2005
Posts: 19216
|
|
|
Yes there is. Both Freddy and I were merely pointing out the removal technique in general.
|
 |
Warren Bell
Ranch Hand
Joined: Dec 20, 2000
Posts: 55
|
|
OK, I am confused. I thought the newer version of the for loop can work off a Collection as long as the Collection implements Iterable which I thought all Collections do now after Java 5. I took this quote off a site, but have read this same thing elsewhere.
http://www.clanproductions.com/java5.html
On the up side, the new form can be applied to both arrays and collections seamlessly. In the expression for(<variable definition> : <expression>), the expression part can either be an instance of an array or an object that implements the Iterable interface. In Java 5 onwards, all java.util collection classes implement this interface, and so the 'new' form of the for loop can be used instead of an Iterator to iterate through any collection. This also gives developers a hook by making their classes Iterable, they can make them available for use within new forms of the for loop.
Here's an example using the java.util.LinkedHashSet.
Collection<Integer> scores = new LinkedHashSet<Integer>();
scores.add(99); // Use of auto boxing
scores.add(88);
scores.add(77);
for(Integer score : scores) {
System.out.println("This score is " + score);
}
Dosen't the loop get an Iterator to work from and therefore it is safe to remove an object from the Collection?
|
 |
Garrett Rowe
Ranch Hand
Joined: Jan 17, 2006
Posts: 1295
|
|
|
When using the enhanced for loop on an Iterable object, behind "under the covers" an iterator is used, however your program doesn't have access to it. The enhanced for loop has very specific use-cases, as you have been shown, the case where you need direct access to the Iterator is not one of them.
|
Some problems are so complex that you have to be highly intelligent and well informed just to be undecided about them. - Laurence J. Peter
|
 |
Rob Spoor
Sheriff
Joined: Oct 27, 2005
Posts: 19216
|
|
|
The for-each loop is only meant when you only want to access each element, not when you need to modify the collection (or iterable) itself.
|
 |
salvin francis
Ranch Hand
Joined: Jan 12, 2009
Posts: 915
|
|
Its similar to what we indians call
Taking an axe and chopping off the branch you are sitting upon.
you know the end result dont you ?
Another example, writing (rather deleting a line of) the same file that you are currenty reading (i wonder if thats permissible)
|
 |
 |
|
|
subject: for loop question
|
|
|