0

I get a concurrentModificationException at allStates.addAll(states) in the code below. How can I avoid this?

public synchronized Set<String> getAllStates(String clientName, Map<String, Set<String>> allClientStates) {
    Set<String> allStates = new ConcurrentSkipListSet<>();
    final Set<String> keySet = allClientStates.keySet();
    for(String key: keySet) {
      Set<String> states = allClientStates.get(key);
      if(states != null)
        allStates.addAll(states);
    }
    return allStates;
  }

This is the top of the stacktrace

exception": "null\njava.util.ConcurrentModificationException\n\tat java.util.HashMap$HashIterator.nextNode(HashMap.java:1445)\n\tat java.util.HashMap$KeyIterator.next(HashMap.java:1469)\n\tat java.util.AbstractCollection.addAll(AbstractCollection.java:343)\n\tat com.xxx.config.ClientDashboardConfig.getAllStates(ClientDashboardConfig.java:312)
Deepak Gopal
  • 155
  • 4
  • 18
  • 1
    You seem to be modifying the map elsewhere. Note also that there doesn't seem to be a reason for using the keys at all: `allClientStates.valueSet().stream().flatMap(Set::stream).collect(toSet())`. – chrylis -cautiouslyoptimistic- Aug 11 '20 at 02:39
  • Try using a basic `Set` type, like `HashSet` instead of `ConcurrentSkipListSet`. Methinks part of the issue is that the code is running too fast, and you have more than one `allAll` method executing at the same time on the object. A `HashSet` should resolve the issue. – Yserbius Aug 11 '20 at 02:39
  • This project is using Java 8, hence I have updated the piece with this code ```allClientStates.values() .stream() .flatMap(Set::stream) .collect(Collectors.toSet());``` – Deepak Gopal Aug 11 '20 at 03:39
  • Hey man, if my answer solved your problem, go ahead and accept it. This site runs on volunteer effort, least you can do is appreciate people's time. – Abhijit Sarkar Aug 11 '20 at 03:41
  • Still getting the concurrentModificationException exception after making the above changes. – Deepak Gopal Aug 12 '20 at 01:35
  • Getting `entrySet()` instead of `keySet()` solves the issue. In the question I was trying to iterate the keySet and then get value from it, which was causing the exception. – Deepak Gopal Aug 12 '20 at 16:17
  • Even using entrySet() didn't help the cause, still getting the same exception. – Deepak Gopal Aug 13 '20 at 00:53
  • The concurrentModificationException was happening at `allStates.addAll(states);`. So I just added the local variable `allStates` in a Synchronized block like this ```synchronized (allStates) {} ``` and did all the transaction with it inside that block. – Deepak Gopal Aug 27 '20 at 03:10

2 Answers2

2
allClientStates.values().stream()
    .flatMap(keys -> keys.stream())
    .collect(Collectors.toSet());
Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
  • This doesn't solve the problem. I still get ConcurrentModificatinoException after modifying code to ```The current answers don't solve the problem. I changed my code to ``` Set allStates = allClientStates.values().stream().flatMap(Set::stream).collect(Collectors.toSet()); ``` and I still get the exception ```` – Deepak Gopal Aug 12 '20 at 01:34
0

I didn't get why do you need the ConcurrentSkipListSet and the clientName. Is this code complete?

Also not clear if there's JVM version limitation

Using java 8 you can do like this:

allClientStates.values()
.stream()
.flatMap(Collection::stream)
.collect(Collectors.toSet());
  • I was experimenting and also removed some other unrelated code from this function before I posted. Hence you see ConcurrentSkipListSet and an unused param. I'll try your suggestion. – Deepak Gopal Aug 11 '20 at 03:37
  • This doesn't solve the problem. I still get ConcurrentModificatinoException after modifying code to ```The current answers don't solve the problem. I changed my code to ``` Set allStates = allClientStates.values().stream().flatMap(Set::stream).collect(Collectors.toSet()); ``` and I still get the exception ```` – Deepak Gopal Aug 12 '20 at 01:34
  • @DeepakGopal can you please provide a parameter example so I can reproduce the issue? – Guilherme Brabo Aug 12 '20 at 05:00
  • ``` final Set>> entrySet = allClientStates.entrySet(); for(Map.Entry> key: entrySet) { Set states = key.getValue(); if(states != null) allStates.addAll(states); }``` This solves the problem. Thanks for the help @GuilhermeBrabo – Deepak Gopal Aug 12 '20 at 16:18