属性相同的两个Java类,equals生效但List.contains为何返回false?
List.contains()返回false但equals()返回true的原因及解决方案
核心原因:List.contains()的比较方向与equals对称性缺失
Java中List.contains(Object o)的底层逻辑是遍历集合元素,调用传入参数o的equals()方法和集合中的元素逐一比较,而非反过来用集合元素的equals()去匹配参数。
你的场景中:
RelocationDisabledProduct重写了equals(),可以识别Item类型对象,属性相同时返回true(即relocationDisabledProduct.equals(item)为true)- 但
Item类的equals()未处理RelocationDisabledProduct类型对象——要么没重写(使用Object默认的引用比较),要么重写后仅判断同类型的Item,导致item.equals(relocationDisabledProduct)返回false
当调用list.contains(item)时,集合会用item.equals(集合中的RelocationDisabledProduct元素)做比较,结果全为false,最终contains()返回false。
解决方案
方案1:修复equals的对称性
根据Java的equals规范,若a.equals(b)为true,则b.equals(a)必须也为true(对称性要求)。因此需要修改Item类的equals()方法,让它能识别RelocationDisabledProduct类型对象,属性相同时返回true。
同时要同步修改hashCode()方法,确保属性相同的Item和RelocationDisabledProduct返回相同哈希值(否则HashSet、HashMap等哈希集合会出现异常)。
示例代码:
// Item类的equals和hashCode重写 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null) return false; // 同时兼容Item和RelocationDisabledProduct类型 if (o instanceof Item) { Item that = (Item) o; return Objects.equals(this.getId(), that.getId()); } else if (o instanceof RelocationDisabledProduct) { RelocationDisabledProduct that = (RelocationDisabledProduct) o; return Objects.equals(this.getId(), that.getId()); } return false; } @Override public int hashCode() { return Objects.hash(getId()); // 仅用共同属性计算哈希值 }
方案2:转换类型后调用contains
如果无法修改Item类代码,可以将Item对象转换为RelocationDisabledProduct对象后,再传入contains()方法:
// 同步Item的属性到RelocationDisabledProduct对象 RelocationDisabledProduct converted = new RelocationDisabledProduct(); converted.setId(item.getId()); // 其他属性逐一同步赋值 boolean exists = list.contains(converted);
内容的提问来源于stack exchange,提问作者arlen
相关产品推荐
相关产品推荐

