1

I understand that this exception is occurring because I'm trying to modify a list while I'm iterating through a list, but I don't understand how to get around it.

    for(Villager e : tasked)
    {
        if(!e.hasTask())
        {
            tasked.remove(e);
        }
    }

The code is pretty self-explanatory. If the villager "e" does not have a task, it should be removed from this list.

Alex
  • 23
  • 3
  • 2
    Nope. Use the iterator loop and remove using iterator's `remove()` method. – Tiny Nov 20 '14 at 06:21
  • possible duplicate of [Remove elements from collection while iterating](http://stackoverflow.com/questions/10431981/remove-elements-from-collection-while-iterating) – alain.janinm Nov 20 '14 at 06:30

4 Answers4

1

Use a ListIterator, which allows you to make changes to the list through which you are iterating.

The code you use is almost indentical in use to an iterator, but removing elements has to be done explicitly using the remove() method of the iterator.

e.g.

    Iterator itr = tasked.iterator(); 
    while(itr.hasNext()) {
        Villager e = itr.next();
        if(!e.hasTask()) {
           itr.remove();
        }
    }
Community
  • 1
  • 1
davek
  • 22,499
  • 9
  • 75
  • 95
0

The ConcurrentModificationException is a RuntimeException that may be thrown by methods that have detected concurrent modification of an object, when such modification is not permissible. An example of not permissible behavior is when a thread tries to modify the internal structure of a Collection, while another thread is iterating over it.

Use Iterator's remove method.

 Iterator<Village> villageItr = tasked.iterator();
   while(villageItr.hasNext()){
     Village e=villageItr.next(); 
     if(!e.hasTask()){
            //remove that element from collection
            villageItr.remove();
        }

   }
Shoaib Chikate
  • 8,665
  • 12
  • 47
  • 70
0

Create separate list (e.g. itemsToRemove), that contains all items you want to remove and then use tasked.removeAll(itemsToRemoveList)

e.g.

   List<Villager> toRemove = new ArrayList();
for(Villager e : tasked)
{
    if(!e.hasTask())
    {
        toRemove.add(e);
    }
}
tasked.removeAll(toRemove);

The Only issue with this approach, if the 'toRemove' list size is very large, you can do the opposite 'ls.retainAll(c)', by only identify what you want to keep.

M-Zaiady
  • 176
  • 2
  • 9
  • 2
    This is not a good solution at all. The real answer is to use the list iterator and remove the desired element right at the moment is found. There is no need for the added overhead of calling `removeAll` afterwards. – hfontanez Nov 20 '14 at 06:34
  • You are right, ' `Iterator.remove` is the only safe way to modify a collection during iteration'. `removeAll` it may be useful only, if you want to keep `toRemove` list for other processing task, other than this. – M-Zaiady Nov 20 '14 at 06:49
0

If you are using java8 you can filter the list using stream API instead of iterating over it by hand.

List<Villager> villagersWithTask = tasked.stream().filter(e -> e.hasTask()).collect(Collectors.toList());
enterbios
  • 1,725
  • 12
  • 13