How do you iterate over a List and remove elements?

K

Knute Johnson

I've got an ArrayList and I want to iterate over the list and remove the
occasional element. If I use the new for loop it throws a
ConcurrentModificationException. An Iterator is going to have the same
problem. There must be some simple way to do this that I'm not thinking
of tonight.

Thanks,
 
P

Patricia Shanahan

Knute said:
I've got an ArrayList and I want to iterate over the list and remove the
occasional element. If I use the new for loop it throws a
ConcurrentModificationException. An Iterator is going to have the same
problem. There must be some simple way to do this that I'm not thinking
of tonight.

Use an explicit Iterator-based loop, and the Iterator's remove method,
not the underlying collection's remove.

Patricia
 
M

Mike Schilling

Knute said:
I've got an ArrayList and I want to iterate over the list and remove
the occasional element. If I use the new for loop it throws a
ConcurrentModificationException. An Iterator is going to have the
same problem.

The ConcurrentModificationException occurs because you're modifying the List
behind the Iterator's back, so to speak. If you use the Iterator to do the
removes you'll be fine.
 
I

Ishwor Gurung

Knute said:
I've got an ArrayList and I want to iterate over the list and remove the
occasional element. If I use the new for loop it throws a
ConcurrentModificationException. An Iterator is going to have the same

The API docs say that ConcurrentModificationException is thrown when you try
to delete an elment in the array list while the iterator is busy traversing
the elements inside it.
problem. There must be some simple way to do this that I'm not thinking
of tonight.

Yes indeed there is. One way to do it is if you can find an element that
you'd like to delete then check it first, delete it and then break out.
Iterator i = l.iterator();
while(i.hasNext())
{
if (i.next().equals("a"))
{
//the key point is breaking out here
l.remove("a");break;
}
}

If you want to delete the whole list, why traverse it in the first place? ;)
hth
 
B

bugbear

Ishwor said:
The API docs say that ConcurrentModificationException is thrown when you try
to delete an elment in the array list while the iterator is busy traversing
the elements inside it.


Yes indeed there is. One way to do it is if you can find an element that
you'd like to delete then check it first, delete it and then break out.

The ConcurrentModificationException is caused by the Iterator
"noticing" that you've changed something under its feet.

The proper solution is to "play nice" with the iterator,
and remove the element AND keep the iterator informed.

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Iterator.html#remove()

BugBear
 
F

Frederick Polgardy

Use an explicit Iterator-based loop, and the Iterator's remove method,
not the underlying collection's remove.

Patricia

In other words:

Iterator i = l.iterator();
while (i.hasNext()) {
if (shouldRemove(i.next()) {
i.remove();
}
}

You can remove as many elements as you need to in the same iteration.

Fred
 
M

Manish Pandit

I've got an ArrayList and I want to iterate over the list and remove the
occasional element. If I use the new for loop it throws a
ConcurrentModificationException. An Iterator is going to have the same
problem. There must be some simple way to do this that I'm not thinking
of tonight.

Thanks,

If you are removing one occassional element, you can just remove it
without iterating (or may be I did not get the situation). Something
like:

synchornize(list){
if(list.contains(obj){
list.remove(obj);
}
}

-cheers,
Manish
 
B

Ben Phillips

Manish said:
if(list.contains(obj){
list.remove(obj);
}

Collections let you do coll.remove(obj) whether or not it's definitely
in there to remove, and return a boolean in case you want to do
something different depending on whether it was there to remove or it
wasn't. This is more efficient as the linked list, array, hash table,
tree, or other backing data structure gets searched only once instead of
twice.
 
P

Patricia Shanahan

Manish said:
If you are removing one occassional element, you can just remove it
without iterating (or may be I did not get the situation). Something
like:

synchornize(list){
if(list.contains(obj){
list.remove(obj);
}
}

That technique works if you want to remove an item with a specified
value. Suppose, for example, you want to remove every string shorter
than 3 characters from a List<String>. It can be done easily using the
Iterator remove method.

What is the purpose of the list.contains(obj) pre-check?

Patricia
 
M

Manish Pandit

What is the purpose of the list.contains(obj) pre-check?

My bad..did not realize contains returns a boolean. Been thinking
about this for a while, and I was wondering if it makes sense to use
an array (or another list..a clone) as an intermediatory. I know this
has scalability and performance numbers against it though. Here is a
little snippet:

ArrayList<Integer> list = new ArrayList<Integer>();
for(int i=0; i<10; i++){
list.add(i);
}
//remove all the even numbers
Integer[] array = new Integer[list.size()];
list.toArray(array);
for( int i:array ){
if( i%2==0 ) {
list.remove(new Integer(i));
}
}
System.out.println(list);

Ofcourse this needs to be synchronized, to make sure the array and the
list do not go out of sync.

-cheers,
Manish
 
P

Patricia Shanahan

Manish said:
What is the purpose of the list.contains(obj) pre-check?

My bad..did not realize contains returns a boolean. Been thinking
about this for a while, and I was wondering if it makes sense to use
an array (or another list..a clone) as an intermediatory. I know this
has scalability and performance numbers against it though. Here is a
little snippet:

ArrayList<Integer> list = new ArrayList<Integer>();
for(int i=0; i<10; i++){
list.add(i);
}
//remove all the even numbers
Integer[] array = new Integer[list.size()];
list.toArray(array);
for( int i:array ){
if( i%2==0 ) {
list.remove(new Integer(i));
}
}
System.out.println(list);

Ofcourse this needs to be synchronized, to make sure the array and the
list do not go out of sync.

-cheers,
Manish

What is the advantage of this, compared to the really dumb, simple,
obvious approach using the Iterator remove() method?


//remove all the even numbers
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
if(it.next() % 2 == 0){
it.remove();
}
}

Patricia
 
M

Manish Pandit

What is the advantage of this, compared to the really dumb, simple,
obvious approach using the Iterator remove() method?

//remove all the even numbers
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
if(it.next() % 2 == 0){
it.remove();
}
}

Not a whole lot except that it is not guaranteed that the Iterator
will support remove().

-cheers,
Manish
 
P

Patricia Shanahan

Manish said:
Not a whole lot except that it is not guaranteed that the Iterator
will support remove().

It is for ArrayList, and any other List that inherits the AbstractList
iterator method and itself supports remove(int):

"This implementation returns a straightforward implementation of the
iterator interface, relying on the backing list's size(), get(int), and
remove(int) methods."

Patricia
 
J

Joshua Cranmer

Manish said:
Not a whole lot except that it is not guaranteed that the Iterator
will support remove().

Nor is it guaranteed that a Collection will support remove() (e.g.,
unmodifiableList). The number of implementations where the list supports
remove() and the iterator doesn't is probably about zero.
 
K

Knute Johnson

Knute said:
I've got an ArrayList and I want to iterate over the list and remove the
occasional element. If I use the new for loop it throws a
ConcurrentModificationException. An Iterator is going to have the same
problem. There must be some simple way to do this that I'm not thinking
of tonight.

Thanks,

Thanks everybody. That's what I was looking for.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,188
Latest member
Crypto TaxSoftware

Latest Threads

Top