Tameem Khan
Tameem Khan

Reputation: 846

Java - Compare two Maps entries for specific keys only

Suppose I have two maps:

    Map<String, String> map1 = Map.of(
        "a", "1",
        "b", "2",
        "c", "3",
        "x", "9"
    );
    Map<String, String> map2 = Map.of(
        "z", "9"
        "a", "1",
        "b", "2",
        "c", "3"
    );

Now I want to compare these maps for only the following keys, to see if they contain the same values: ["a", "b", "c"]

One straightforward approach can be:

public boolean customEquals(Map map1, Map map2){ //please ignore NullPointerException
    return map1.get("a").equals(map2.equals("a"))
            && map1.get("b").equals(map2.equals("b"))
            && map1.get("c").equals(map2.equals("c"));
}

But this is very inefficient and smelly to code if there are many more keys to check. In that case a better approach can be:

public boolean customEquals(Map map1, Map map2) { //please ignore NullPointerException
    Set<String> keys = Set.of("a", "b", "c");
    for (String key : keys) {
        if (!(map1.get(key).equals(map2.get(key)))) {
            return false;
        }
    }
    return true;
}

Is there any better way to do this? (You can recommend popular library functions as well)

Upvotes: 4

Views: 184

Answers (3)

Amir Hossain
Amir Hossain

Reputation: 184

Stream.of("a","b","c").allMatch(key -> map1.get(key).equals(map2.get(key)));

Upvotes: 2

Ryuzaki L
Ryuzaki L

Reputation: 39978

First get the entries of key=[a,b,c] from map1 or map2 into List

List<SimpleEntry<String,String>> res = Stream.of("a","b","c")
                                   .map(key->new AbstractMap.SimpleEntry<String,String>(key, map1.get(key)))
                                   .collect(Collectors.toList());   

And then you can check all these entries are existed in another Map, so in this way you need not to be worry about NullPointerException even any of the Map doesn't having value for [a,b,c]

res.stream().allMatch(entry->map2.entrySet().contains(entry))  //convert map2 to entrySet before using in allMatch

We can also combine both of them into one line

Stream.of("a","b","c")
         .map(key->new AbstractMap.SimpleEntry<String,String>(key, map1.get(key)))
         .allMatch(entry->map2.entrySet().contains(entry));

Upvotes: 3

wooseop
wooseop

Reputation: 337

  private static <K, V> Map<K, V> filterEntries(Map<K, V> map, Collection<K> keys) {
    var entries = map.entrySet()
      .stream()
      .filter(entry -> keys.contains(entry.getKey()))
      .toArray(Map.Entry[]::new);
    return Map.ofEntries(entries);
  }

(Run above at https://repl.it/repls/StickyGaseousAutomatedinformationsystem)

Might not be a better way but I'd prefer to use Streams to filter the map.

Upvotes: 2

Related Questions