Win a copy of Programmer's Guide to Java SE 8 Oracle Certified Associate (OCA) this week in the OCAJP forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

for loop question

 
Warren Bell
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 959
Eclipse IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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().
 
Vijitha Kumara
Bartender
Posts: 3914
9
Chrome Fedora Hibernate
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Pie
Posts: 20606
60
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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:
 
salvin francis
Bartender
Posts: 1305
10
Eclipse IDE Google Web Toolkit Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
isnt there a clear method ??
 
salvin francis
Bartender
Posts: 1305
10
Eclipse IDE Google Web Toolkit Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I meant

 
Rob Spoor
Sheriff
Pie
Posts: 20606
60
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes there is. Both Freddy and I were merely pointing out the removal technique in general.
 
Warren Bell
Ranch Hand
Posts: 56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 1296
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Rob Spoor
Sheriff
Pie
Posts: 20606
60
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Bartender
Posts: 1305
10
Eclipse IDE Google Web Toolkit Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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)

 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic