如何筛选MapA中所有包含MapB键作为子串的键?
实现思路
- 提前把mapB的所有键存入HashSet,利用HashSet O(1)的查询特性避免嵌套循环
- 仅遍历一次mapA的键,按需判断匹配条件即可,整体执行效率更高
固定前缀场景(你的示例符合该场景)
如果mapA的键格式固定为mapB键|xxx|xxx的前缀拼接格式,直接截取前缀判断即可:
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; public class MapMatchTest { public static void main(String[] args) { Map<String, String> mapA = new HashMap<>(); mapA.put("aaa|111|osdf", "value1"); mapA.put("bbb|222|dfsf", "value2"); mapA.put("ccc|333|xsdv", "value3"); Map<String, String> mapB = new HashMap<>(); mapB.put("aaa", "valueM"); mapB.put("bbb", "valueN"); // 取出mapB的键集合 Set<String> bKeySet = mapB.keySet(); List<String> result = new ArrayList<>(); // 仅遍历一次mapA,无嵌套循环 for (String aKey : mapA.keySet()) { // 只分割一次取前缀,避免无用分割 String prefix = aKey.split("\\|", 2)[0]; if (bKeySet.contains(prefix)) { result.add(aKey); } } // 输出结果:aaa|111|osdf bbb|222|dfsf result.forEach(System.out::println); // 也可以用流式写法简化代码 List<String> streamResult = mapA.keySet().stream() .filter(aKey -> bKeySet.contains(aKey.split("\\|", 2)[0])) .collect(Collectors.toList()); } }
任意子串场景
如果mapB的键可能出现在mapA键的任意位置,使用以下写法即可:
List<String> result = mapA.keySet().stream() .filter(aKey -> bKeySet.stream().anyMatch(aKey::contains)) .collect(Collectors.toList());
注:该写法内部的短stream迭代不属于业务层面的嵌套循环,mapB规模不大的情况下性能完全够用。如果mapB键的数量极多,可以提前构建AC自动机做多模式匹配,可把整体复杂度降到O(n+m)级别。
内容的提问来源于stack exchange,提问作者zhwlx22
相关产品推荐
相关产品推荐

