How to remove innermap key using java 8 streams

I am trying to learn java8 streams , I have the following code

List<HashMap<String, HashMap<String, String>>> map2 = new ArrayList<>();

HashMap<String, String> innerMap = new HashMap<>();
innerMap.put("a1", "hermione");
innerMap.put("a2", "harry");
innerMap.put("a3", "ron");

HashMap<String, HashMap<String, String>> outermap = new HashMap<>();
outermap.put("friends", innerMap);

List<HashMap<String, HashMap<String, String>>> list = new ArrayList<>();
list.add(outermap);

i want to remove harry from inner map and the same structure ( List>>) should be retained, how do i achieve that using java 8 streams?

2 answers

  • answered 2020-05-22 12:38 Arvind Kumar Avinash

    For such a requirement, you should add a copy of the map instead of the original map as shown below:

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class Main {
        public static void main(String[] args) {
            Map<String, String> innerMap = new HashMap<>();
            innerMap.put("a1", "hermione");
            innerMap.put("a2", "harry");
            innerMap.put("a3", "ron");
    
            Map<String, Map<String, String>> outermap = new HashMap<>();
            outermap.put("friends", new HashMap<>(innerMap));
    
            List<Map<String, Map<String, String>>> list = new ArrayList<>();
            list.add(new HashMap<>(outermap));
    
            innerMap.remove("a2");
            System.out.println(innerMap);
            System.out.println(list);
        }
    }
    

    Output:

    {a1=hermione, a3=ron}
    [{friends={a1=hermione, a2=harry, a3=ron}}]
    

    Had I added the original map (the way you have done), deleting an entry from it would have affected the list as well.

  • answered 2020-05-22 14:31 Nikolas

    You really need to use here as long as you only want to remove a certain map entry while keeping the whole structure:

    list.forEach(map -> map.forEach(
        (key, value) -> value.entrySet()
            .removeIf(entry -> "harry".equals(entry.getValue()))));
    

    If you insist on using Stream API, be prepare for complicated handling with entries and dictionaries themselves as long as the Stream API is suitable to work with collections. Take a look:

    List<Map<String, Map<String, String>>> newList = list.stream()
        .map(outer -> outer.entrySet().stream()
            .map(inner -> new SimpleEntry<>(
                inner.getKey(),
                inner.getValue().entrySet().stream()
                    .filter(entry -> !"harry".equals(entry.getValue()))
                    .collect(Collectors.toMap(Entry::getKey, Entry::getValue))))
            .collect(Collectors.toMap(Entry::getKey, Entry::getValue)))
        .collect(Collectors.toList());
    

    Moreover, as already stated, the classes are the way more suitable to represent such complicated data structures.