如何在Guava的Maps.difference中使用通配符忽略指定字段比对差异
Guava Maps.difference 通配符字段校验解决方案
Guava 原生的Maps.difference没有内置通配符支持,可通过以下两种方式实现需求:
方案1:预处理过滤法(实现简单,易调试)
核心逻辑:先校验必填字段存在,再过滤掉需要忽略值的字段后对比
- 第一步:校验模式Map的所有key都在实际返回的Map中存在,确保必填字段没有缺失
- 第二步:分别复制模式Map和实际Map为临时对象,移除所有模式Map中值为
*的key - 第三步:用
Maps.difference对比处理后的两个临时Map,返回无差异即校验通过
代码示例:
import com.google.common.collect.Maps; import java.util.Map; public class MapDiffTest { public static boolean validate(Map<String, Object> actualMap, Map<String, Object> patternMap) { // 先校验所有预期key都存在 if (!actualMap.keySet().containsAll(patternMap.keySet())) { return false; } // 过滤掉值为*的字段 Map<String, Object> filteredPattern = Maps.filterEntries(patternMap, entry -> !"*".equals(entry.getValue())); Map<String, Object> filteredActual = Maps.filterKeys(actualMap, filteredPattern.keySet()::contains); // 对比剩余字段 return Maps.difference(filteredPattern, filteredActual).areEqual(); } }
方案2:自定义值等价比较器(功能更灵活)
使用Maps.difference的重载方法,传入自定义的值对比逻辑,当模式值为*时直接判定相等:
import com.google.common.base.Equivalence; import com.google.common.collect.Maps; import java.util.Map; public class MapDiffTest { private static final Equivalence<Object> WILDCARD_SUPPORT_EQUIVALENCE = new Equivalence<>() { @Override protected boolean doEquivalent(Object expected, Object actual) { // 模式值为*时直接判定相等 if ("*".equals(expected)) { return true; } // 否则正常对比值 return expected.equals(actual); } @Override protected int doHash(Object o) { return o.hashCode(); } }; public static boolean validate(Map<String, Object> actualMap, Map<String, Object> patternMap) { // 先校验所有预期key都存在 if (!actualMap.keySet().containsAll(patternMap.keySet())) { return false; } return Maps.difference(patternMap, actualMap, WILDCARD_SUPPORT_EQUIVALENCE).areEqual(); } }
注意事项
- 需固定将模式Map作为
Maps.difference的第一个入参,实际返回Map作为第二个入参,避免通配符逻辑判断错误 - JSON转Map时需统一值的类型,避免因字符串/数字类型不匹配导致的对比失败
内容的提问来源于stack exchange,提问作者R. Del
相关产品推荐
相关产品推荐

