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.

2

4 Answers 4

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();
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

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();
        }

   }

Comments

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.

2 Comments

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.
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.
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());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.