如何不手动校验字段即可完成自定义类元素的Set集合内容比对
解决方案
- 最规范的方案是重写
Capability类的equals()和hashCode()方法
Java中HashSet、LinkedHashSet等基于哈希的集合,判断元素是否相等的底层逻辑依赖两个方法:先比对hashCode()返回值,值相等再调用equals()判断,默认继承自Object的实现是比对对象内存地址,所以JSON反序列化出来的不同实例即使业务字段完全一致,也会被判定为不同对象,导致containsAll()失效。
现在所有Java IDE(IntelliJ IDEA、Eclipse等)都支持一键生成这两个方法,只需要选择参与业务相等判断的字段即可,不需要手动逐字段写比对逻辑。后续新增字段时,重新生成一次两个方法即可,不会出现硬编码维护问题。
修改后的Capability类示例:
public class Capability { private String name; public Capability(){ } public Capability(String name){ this.name = name; } public String getName(){ return name; } @Override public String toString(){ return "Capability: "+name+"."; } // 新增重写的equals和hashCode @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Capability that = (Capability) o; return java.util.Objects.equals(name, that.name); // 后续新增字段后,IDE重新生成时会自动添加对应比对逻辑 } @Override public int hashCode() { return java.util.Objects.hash(name); // 后续新增字段后,IDE重新生成时会自动把新字段加入哈希计算 } }
修改完成后,你原来注释掉的return this.getPrimitive().getCapabilities().containsAll(this.getReqCapabilities());代码就可以直接正常使用,不需要额外修改校验逻辑。
- 如果你不能修改
Capability类的原有定义,可以使用通用反射比对方案
可以基于反射写通用的字段比对方法,也可以用常用工具库的反射比对能力实现全字段自动匹配,不需要硬编码指定字段,示例代码如下:
public boolean allCapabilitiesMet(){ return getReqCapabilities().stream() .allMatch(reqCap -> getPrimitive().getCapabilities().stream() .anyMatch(primCap -> org.apache.commons.lang3.builder.EqualsBuilder.reflectionEquals(reqCap, primCap)) ); }
这个方案不需要修改Capability类,新增字段时也不需要调整比对代码,但性能比重写equals的方案要差,适合临时使用的场景。
内容的提问来源于stack exchange,提问作者André Rocha
相关产品推荐
相关产品推荐

