2

How can I filter map of map using java stream. I can do it using double loop but I think this is not efficient.

public class MapUsage {
    static Map<Integer, Map<Integer, String>> parentMap = new HashMap<>();
    static Map<String, String> userRole = new HashMap<>();

    public static void main(String ... args){
        initializeData();
        displayMapForUser("user1", parentMap);
//        printMap(parentMap);

    }


    private static void displayMapForUser(String user1, Map<Integer, Map<Integer, String>> parentMap) {
        Integer role = new Integer(userRole.get(user1));
        Map<Integer, Map<Integer, String>> userMap = new HashMap<>();
        Map<Integer, String> childMap = new HashMap<>();
        for(Map.Entry<Integer, Map<Integer, String >> entry : parentMap.entrySet()){
            for(Map.Entry<Integer, String > entry1: entry.getValue().entrySet()){
                if(entry1.getKey().equals(role))
                    childMap.put(entry1.getKey(), entry1.getValue());
            }
            userMap.put(entry.getKey(), childMap);
        }
        printMap(userMap);
    }

    private static void printMap(Map<Integer, Map<Integer, String>> parentMap) {
        for(Map.Entry<Integer, Map<Integer,String> > entry: parentMap.entrySet()){
            System.out.println("key: "+entry.getKey());
            System.out.println("value: "+entry.getValue());
        }
    }

    private static void initializeData() {
        Map<Integer, String > childMap1 = new HashMap<>();
        Map<Integer, String > childMap2 = new HashMap<>();
        userRole.put("user1", "1");
        userRole.put("user2", "2");
        userRole.put("user3", "3");
        userRole.put("user4", "4");

        childMap1.put(1, "one");
        childMap1.put(2, "two");
        childMap1.put(3, "three");
        childMap1.put(4, "four");
        parentMap.put(1, childMap1);

        childMap2.put(1, "one");
        childMap2.put(2, "two");
        childMap2.put(3, "three");
        parentMap.put(2, childMap2);
    }
}

Output is:

key: 1
value: {1=one}
key: 2
value: {1=one}
4
  • 2
    What version of Java are you using? Commented Feb 25, 2020 at 16:17
  • 1
    @Wiingreen - Java 8 Commented Feb 25, 2020 at 16:21
  • What do you mean by "filter"? As in only including members of the 2nd map that match some criterion? Commented Feb 25, 2020 at 16:21
  • Yes. I would like to return the result of inner map based on the role of user. Commented Feb 25, 2020 at 16:31

1 Answer 1

5

You could use Collectors.toMap there as:

Map<Integer, Map<Integer, String>> userMap = parentMap.entrySet().stream()
        .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue()
                .entrySet().stream()
                .filter(en -> en.getKey().equals(role))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))));

But note, there is no significant performance efficiency that you gain here. Just readability and you could have possibly written that as :

Map<Integer, Map<Integer, String>> usersMap = new HashMap<>(parentMap);
usersMap.values().forEach(innerMap -> innerMap.entrySet().removeIf(en -> !en.getKey().equals(role)));
Sign up to request clarification or add additional context in comments.

1 Comment

I would note that this has about the same complexity as the original solution, but the increased readability is a good improvement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.