0

I am trying to create simple JAVA program. But since last day, I am having this issue, I cannot fix.

public void receiveUpdate(ArrayList<Connection> connections) {

    for(Connection senderConnection : connections) {

        for(Connection receiverConnection : this.connections) {

            if(senderConnection.getDestination() == receiverConnection.getDestination()) {

                if(senderConnection.getDistance() + 1 < receiverConnection.getDistance()) {

                    senderConnection.setEnabled(false);
                    senderConnection.setDistance(senderConnection.getDistance() + 1);

                    this.connections.remove(receiverConnection);
                    this.connections.add(senderConnection);
                }
            }
        }

        senderConnection.setEnabled(false);
        senderConnection.setDistance(senderConnection.getDistance() + 1);

        this.connections.add(senderConnection);
    }
}

In this method I always get error:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at router.Router.receiveUpdate(Router.java:56)
    at router.Router.sendUpdate(Router.java:49)
    at loader.Loader.notifyNetworkChanges(Loader.java:61)
    at loader.Loader.main(Loader.java:102)

I have noticed, that exception doesn't appear if I comment block:

senderConnection.setEnabled(false);
senderConnection.setDistance(senderConnection.getDistance() + 1);

this.connections.add(senderConnection);

Can anyone tell me, where is the problem?

0

4 Answers 4

2

ConcurrentModificationException This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible. The problem is here

this.connections.remove(receiverConnection);

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible. For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.

Check this out

To solve your problem you need to use Iterator and remove() method like this

Iterator<String> connectionsIterator = connections.iterator();

while (connectionsIterator.hasNext()) {

    if (senderConnection.getDistance() + 1 < receiverConnection.getDistance()){

        connectionsIterator.remove();
// add the connection to another list other than this.connections.add(senderConnection);
// then when you finish add them back the this.connections
// so you avoid modifying this.connections
   }
} 
Sign up to request clarification or add additional context in comments.

2 Comments

And how can I get senderConnection and receiverConnection if there is no for-while loop?
You can have two while loops just like you did in the quest however they don't need to be for loops and you must use the iterator instead of the original collections
1

You are actually modifying the collections, while iterating.

this.connections.remove(receiverConnection);
this.connections.add(senderConnection);

Use an Iterator and call remove():

Iterator<String> iter = connections.iterator();

while (iter.hasNext()) {

    if (someCondition)
        iter.remove();
}

Use Iterator remove method instead of ArrayList

3 Comments

And how can I get element from collections such as connections or this.connections to call specific method for its object?
@JacobJones use iterator on this.connections.
Yea. But the problem is that in my example there are ArrayList elements called senderConnection and receiverConnection. These two are objects of class Connection. I want to call class specific methods for them. bur, without a for-while loop, I don't have these objects...
0

If you are modifying (eg deleting from) the same list you are looping then you are bound to get the ConcurrentModificationException

You can either use an iterator as @ankur-singhal mentioned or make a deep copy of the list and remove from that copy. Then you can assign the reference of the original list to point to the new one that has the modifications.

Another "greedy" approach (but without using iterators) would be to keep all items to be removed in another new list and after ending your for loop then call removeAll(listOfConnectionsToBeRemoved), for example:

before your for loops

ArrayList<Connection> connectionsToBeRemoved = new ArrayList<Connection>();

inside your for loops

connectionsToBeRemoved.add(receiverConnection)

after ending your for loops

this.connections.removeAll(connectionsToBeRemoved)

*you may do the same for connections to be added. Keep them in a new list and then add them all to your connection list.

1 Comment

After adding one more list (connectionsToBeAdded), exception doesn't occur anymore. Thank you!
0

You are looping through this.connections and inside you are trying to remove from this.connections this will java.util.ConcurrentModificationException. Change your code to use iterator.

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.