Home > Back-end >  Find a Value in a HashMap mapped to a Key formated as a Regex that matches the given String
Find a Value in a HashMap mapped to a Key formated as a Regex that matches the given String

Time:06-30

I have a requirement where I need to find the values from the HashMap where few keys are stored in regex format. For example, some of the keys are in this format "abc.\*.xyz", "efg.\*.asc".

How do I retrieve the value for "abc.unset.xyz"?

Please note that only few keys are in this format. Others may not have dot delimiter at all, and they may be just a single word like "abc". In short, map's keyset contains a mix of both.

CodePudding user response:

You can iterate over the set of entries of the map either using a loop or a stream and filter out the entry containing a regular expression a key that matches the given string.

Alternatively, you can perform iteration over the set of keys as @Robby Cornelissen suggested in the comments, but if you change the type of map let's say to TreeMap your code will get an additional cost because accessing the value will no longer be O(1), but O(log n). With entries, you always have direct references to a key and a value together, and retrieving the value would always be O(1).

If you expect only a single target key to be present, then it can be done like that using Stream API:

String seachKey = "abc.unset.xyz";
Map<String, String> map = new HashMap<>();

String values = map.entrySet().stream()
    .filter(entry -> seachKey.matches(entry.getKey()))
    .map(Map.Entry::getValue)
    .findFirst()
    .orElseThrow(); // or .orElse(defaultValue); depending on your needs

Sidenote: you're note escaping dots in your regular expressions, dot in regex denotes a symbol of any kind. I guess you've probably meant:

"abc\\.. \\.xyz" - "abc" dot one or more symbols dot "xyz"

CodePudding user response:

some of the keys are in this format abc..xyz, efg..asc. How do i retrieve the value for abc.unset.xyz?

You are describing a step where you need to take an actual key (such as "abc.unset.xyz") and convert that to it's equivalent "pattern key" (such as "abc.*.xyz"). In some cases, the original key is the same as the "pattern key" in the map (such as "abc").

This sounds like:

  • prior to calling .get() on your map, convert the key using a function
  • that function applies a regular expression to the key value itself, turning a string like "abc.unset.xyz" into a string like "abc.*.xyz"

Here's an example of what that function could look like:

public static String getUpdatedKey(String key) {
    return key.replaceAll("\\.[a-z] \\.", ".*.");
}

Here's a simple demo of:

  • a map with a literal key "abc.*.xyz"
  • caller asking if the long key "abc.unset.xyz" is present (it isn't, print null)
  • caller getting the updated key, and asking if that is present (it is, print 1)
Map<String, Integer> map = new HashMap<>();
map.put("abc.*.xyz", 1);

String fullKey = "abc.unset.xyz";
System.out.println(map.get(fullKey));

String updatedKey = getUpdatedKey(fullKey);
System.out.println(map.get(updatedKey));

Running above prints

null
1

This example also works if the input key (such as "abc") doesn't contain the other pattern parts:

map.put("abc", 2);
System.out.println(map.get(getUpdatedKey("abc")));

Running above prints 2.

You might need to adjust the regular expression in getUpdatedKey(), but this seems like a workable format to follow.

  • Related