1

I am trying to remove objects from a list and I get the following exception :

failure:java.util.ConcurrentModificationException null

And this is how I try to remove the objects from the list:

private List<testVO> removeDuplicateEntries(List<testVO> sessionList,List<testVO> dbList){


        for (Iterator<testVO> dbIterator = dbList.listIterator(); dbIterator.hasNext(); ) {
            testVO voDB = dbIterator.next();

            for (Iterator<testVO> sessionIterator = sessionList.iterator(); sessionIterator.hasNext();) {
                testVO voSession = (testVO) sessionIterator.next();

                if(voDB.getQuestionID().intValue() == voSession.getQuestionID().intValue()){
                    //remove the object from sesion list
                    sessionIterator.remove();
                    //Add the object from DB to session list
                    sessionList.add(voDB);
                }

            }

        }

        return sessionList;
    }

I would like to remove the duplicates which are currently in sessionList and add the ones from dbList.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
Joe
  • 4,460
  • 19
  • 60
  • 106

3 Answers3

6

You cannot add to the sessionList on iterating through it.

    for (Iterator<testVO> dbIterator = dbList.listIterator(); dbIterator.hasNext(); ) {
        testVO voDB = dbIterator.next();

        List<testVO> toBeAdded = new LinkedList<>();
        for (Iterator<testVO> sessionIterator = sessionList.iterator(); sessionIterator.hasNext();) {
            testVO voSession = (testVO) sessionIterator.next();

            if(voDB.getQuestionID().intValue() == voSession.getQuestionID().intValue()){
                //remove the object from sesion list
                sessionIterator.remove();
                //Add the object from DB to session list
                //CANNOT DO: sessionList.add(voDB);
                toBeAdded.add(voDB);
            }
        }
        Collections.addAll(sessionList, toBeAdded);
    }
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
2
List<testVO> toRemove = ...
List<testVO> toAdd = ...

// in loop
toRemove.add(removed);
toAdd.add(added);

//after appropraite loops
yourList.addAll(toAdd);
yourList.removeAll(toRemove);

the toRemove is added here in case one is using for-each version of the for loop; it is better to remove an element from collection through iterator, since it does not consume any more resources for searches.

Dariusz
  • 21,561
  • 9
  • 74
  • 114
  • Adding is easy, but removing is hard - each item has to be searched for linearly as there is no indication where it may be. It's better to remove when the item is actually found - using the Iterator. – RealSkeptic Oct 05 '15 at 11:29
1

As was explained in other answers, you can't add to the collection while iterating it. You have to do the modification of information using the iterator itself - or wait until you finish iterating.

However, a plain Iterator just allows you to remove items. Using a ListIterator you can also add to the list. Thus, if you use sessionList.listIterator() rather than sessionList.iterator(), you'll be able to add the item while you iterate.

This has a different result than adding to the list (if that was possible), though. Suppose you have a list:

[ A, B, C, D, E ]

And you wanted to replace C with c and D with d. If you use the list iterator, your result will be:

[ A, B, c, d, E ]

While adding the items to the list would result in:

[ A, B, E, c, d ]

So, if you want the items to be appended to the end, you should do as other answers have pointed, collect all the items you want to add, and addAll when you finish iterating sessionList.

But if you want to replace them in place ([ A, B, c, d, E ]), you can use the list iterator:

for (ListIterator<testVO> sessionIterator = sessionList.listIterator(); sessionIterator.hasNext();) {
    testVO voSession = (testVO) sessionIterator.next();

    if(voDB.getQuestionID().intValue() == voSession.getQuestionID().intValue()){
        //remove the object from sesion list
        sessionIterator.remove();
        //Add the object from DB to the session list 
        sessionIterator.add(voDB);
    }

}

The differences is that sessionIterator is now declared as a ListIterator and initialized with sessionList.listIterator(), and also that instead of sessionList.add() you are using sessionIterator.add().

Note that the add operation on ListIterator is optional, so, depending on the list implementation, this method may not work and throw an UnsupportedOperationException.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79