Search code examples
javaiteratorhashmapconcurrentmodification

ConcurrentModificationException in HashMap


I am taking the insurance details from user and saving them in a hashmap. And I have button called SAVE. So only, when user clicks on this button all insurances should save in Database So I am taking a random generated id as reference until I save the details in Database After saving in database, I need to update this hashmap with key as autogenerated id

public void saveInformationInDatabase(int patientId)
{
    // getAllInsurances returns HashMapn<Integer, HashMap<Integer, InsuranceInformation>>
    Iterator<Map.Entry<Integer, InsuranceInformation>> insurances = getAllInsurances().get(patientId).entrySet().iterator();
    while(insurances.hasNext())
    {
        InsuranceInformation insuranceInformation = insurances.next().getValue();
        if (insuranceInformation.getStatus() == Status.OLD)
            continue;
        else if (insuranceInformation.getStatus() == Status.NEW)
        {
            // Saving the Information in database, and returning auto generated ID
            int licId = saveInformation(insuranceInformation);
            // So, i need to update insuranceInformation with autogenerated ID
            // Because previous id is randomly generated number
            insuranceInformation.setLicID(licId);
            insuranceInformation.setStatus(InsuranceObject.Status.OLD);
            // Below line gives me ConcurrentModificationException
            getAllInsurances().get(patientId).put(licId, insuranceInformation); // Storing the updated information with newly generated id as key, in hashmap
            insurances.remove(); // and here, removing the old hashmap entry
        }
    }
}

Solution

  • getAllInsurances().get(patientId).put(licId, insuranceInformation); is updating the Map while you're attempting to iterate it, this is causing the exception as you can't modify a collection while you're iterating it.

    Instead, you should use a second Map to store the updated values and the use Map#putAll to resync the two, for example...

    // Test map full of values...
    Map<Integer, String> mapTest = new HashMap<>(25);
    for (int index = 0; index < 10; index++) {
        mapTest.put(index, Integer.toString(index));
    }
    
    // Grab an iterator
    Iterator<Map.Entry<Integer, String>> insurances = mapTest.entrySet().iterator();
    // Create a temp map for the new values
    Map<Integer, String> newValues = new HashMap<>(25);
    while(insurances.hasNext()) {
    
        Map.Entry<Integer, String> entry = insurances.next();
        int key = entry.getKey();
        // Make the comparison about what we want to do, here
        // we're removing even keys
        if (key % 2 == 0) {
            // Remove the old entry
            insurances.remove();
            // Use the temp map to create a new entry
            newValues.put(key * 10, entry.getValue());
        }
    
    }
    
    // Merge the results
    mapTest.putAll(newValues);
    

    As one possible solution