如何匹配HashMap中regex格式的Key查找对应映射Value
混合普通Key与正则Key的HashMap匹配方案
原生HashMap是基于Key的哈希值做精确匹配的,无法直接识别正则格式的Key,按以下逻辑实现即可覆盖你的场景:
- 优先走精确匹配逻辑:查询时先将输入字符串作为Key直接从Map中取值,命中则直接返回。这一步时间复杂度为O(1),性能最优,可覆盖所有普通字符串Key的场景,完全不会干扰非正则Key的匹配结果。
- 精确匹配未命中时,走正则匹配逻辑:
你存储的带*的Key属于类路径通配格式,*代表匹配一个不含.的连续段(即两个点之间的任意内容),不能直接作为正则表达式使用,需要提前做规则转换:- 将Key中的正则特殊字符做转义处理,避免
.等字符被识别为正则通配符 - 将通配符
*替换为[^.]+(匹配不含点的连续字符,刚好对应单个路径段) - 在转换后的正则表达式首尾加
^和$做全串匹配,避免部分匹配导致的误命中
举个例子,存储的Keyabc.*.xyz转换后得到的正则为^abc\.[^.]+\.xyz$,可以精准匹配abc.unset.xyz这类格式的字符串,不会跨段误匹配。
- 将Key中的正则特殊字符做转义处理,避免
- 提前做性能优化:不要在每次查询时临时编译正则表达式,初始化Map时就将所有带
*的正则格式Key提前编译为Pattern对象,和对应的Value一起缓存到列表中。精确匹配未命中时,直接遍历缓存的正则规则做匹配即可,避免重复编译正则带来的性能损耗。
参考实现代码(Java)
import java.util.HashMap; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; public class WildcardKeyMap { // 存储普通精确匹配的键值对 private final HashMap<String, Object> exactStore = new HashMap<>(); // 缓存提前编译好的正则规则和对应值 private final List<RegexMatchRule> regexRules = new ArrayList<>(); public void put(String key, Object value) { // 按是否包含通配符*区分两类Key if (key.contains("*")) { // 转义所有正则特殊字符,再将通配*替换为单段匹配规则,加全串匹配锚点 String quotedKey = Pattern.quote(key); String regex = "^" + quotedKey.replace("*", "[^.]+") + "$"; Pattern compiledPattern = Pattern.compile(regex); regexRules.add(new RegexMatchRule(compiledPattern, value)); } else { exactStore.put(key, value); } } public Object get(String input) { // 第一优先级:精确匹配 Object exactResult = exactStore.get(input); if (exactResult != null) { return exactResult; } // 第二优先级:遍历正则规则匹配 for (RegexMatchRule rule : regexRules) { if (rule.pattern.matcher(input).matches()) { return rule.value; } } // 无匹配结果按业务需求处理,这里返回null return null; } // 内部类存储编译后的正则与对应值 private static class RegexMatchRule { Pattern pattern; Object value; RegexMatchRule(Pattern pattern, Object value) { this.pattern = pattern; this.value = value; } } // 测试验证 public static void main(String[] args) { WildcardKeyMap testMap = new WildcardKeyMap(); testMap.put("abc", "普通Key:abc对应的值"); testMap.put("abc.*.xyz", "正则Key:abc.*.xyz对应的值"); testMap.put("efg.*.asc", "正则Key:efg.*.asc对应的值"); System.out.println(testMap.get("abc")); // 输出:普通Key:abc对应的值 System.out.println(testMap.get("abc.unset.xyz")); // 输出:正则Key:abc.*.xyz对应的值 System.out.println(testMap.get("efg.demo.asc")); // 输出:正则Key:efg.*.asc对应的值 } }
注意事项:如果Map中存在多个正则Key同时匹配同一个输入的情况(比如同时存储
abc.*.xyz和*.unset.xyz,输入abc.unset.xyz会同时命中两个规则),需要提前定义优先级规则(比如正则Key长度越长优先级越高、按存入顺序优先匹配等),避免返回不符合预期的结果。
内容的提问来源于stack exchange,提问作者johnnesto
相关产品推荐
相关产品推荐

