1
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;


public class HelloWorld{

     public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();

        IntStream.range(0, 20).forEach(i -> map.put(Integer.toString(i), i % 2 == 0 ? null : "ok"));

        for (Map.Entry<String, String> entry : map.entrySet()) {
            if (entry.getValue() == null) {
                map.remove(entry.getKey());
            }
        }
    }
}

This is a sample code where I am trying to delete the null values off the given Hashmap. But this code is giving ConcurrentModificationException. Any idea how to fix this?

EDIT: Thanks to YCF_L, the above code helps if I replace the whole loop with the map.entrySet().removeIf(entity -> entity.getValue() == null);

Problem 2:

What if the hashmap is nested?

  • Case 1 -> I want to delete if value is null
  • Case 2 -> I want to delete if the value is a hashmap whose each element in the nested hash is null and so on if its nested nested.

Ex code:

public static void removeEmptyValues(Map<String, Object> entityMap) {
    for (Map.Entry<String, Object> entry : entityMap.entrySet()) {
        String key = entry.getKey();
        Object value = entry.getValue();
        if (value == null) {
            entityMap.remove(key);
        } else if (value instanceof Map) {
            removeEmptyValues((Map) value);
            if (((Map) value).isEmpty()) {
                entityMap.remove(key);
            }
        }
    }
}
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
Sk. Irfan
  • 299
  • 3
  • 15

1 Answers1

2

You can solve this problem using Collection::removeIf like this :

map.entrySet().removeIf(entity -> entity.getValue() == null);

The reason that this error is thrown is that you are simultaneously iterating the values of a Hashmap, changing it by removing a value and then continue iterating. This is what raises the exception.

See also this answer:

Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • Yes. I am getting the same error with this patch as well. – Sk. Irfan May 04 '18 at 13:35
  • 3
    You need to replace the whole iteration loop with the code provided by YCF_L – Spyros K May 04 '18 at 13:36
  • @Sk.Irfan this is not possible I get `{11=ok, 13=ok, 15=ok, 17=ok, 19=ok, 1=ok, 3=ok, 5=ok, 7=ok, 9=ok}` and note you have to replace all this `for (Map.Entry entry : map.entrySet()) { if (entry.getValue() == null) { map.remove(entry.getKey()); } }` with my code as @SpyrosK mention – Youcef LAIDANI May 04 '18 at 13:37
  • @YCF_L - agreed, but what can be done if its nested hash? – Sk. Irfan May 04 '18 at 13:44
  • what did you mean by nested hash? – Youcef LAIDANI May 04 '18 at 13:45
  • @YCF_L - Edited the question please check. – Sk. Irfan May 04 '18 at 13:52
  • @Sk.Irfan I'm not 100% sure but can you try this please `entityMap.entrySet().removeIf(entity -> entity.getValue() == null || entity.getValue() instanceof Map || (entity.getValue() instanceof Map && ((Map) entity.getValue()).isEmpty()));` or based on the comment of Eugen `entityMap.values().removeIf(entity -> entity == null || entity instanceof Map || (entity instanceof Map && ((Map) entity).isEmpty()));` – Youcef LAIDANI May 04 '18 at 14:01
  • Sorry for increasing the depth of the question. This will work if the nested hashmap is completely empty. But if some values of the nested hash are null and some are having values, we have to clear those nested nulls as well. – Sk. Irfan May 04 '18 at 14:08
  • In this case I think you need a recursive method, I would like to create another question where you can describe every thing. – Youcef LAIDANI May 04 '18 at 14:19