重写hashCode()方法与重写equals()密切相关:这两个方法为在HashMap、HashSet、Hashtable等依赖于比较和哈希函数的集合中正确使用对象奠定了基础。
规则:
equals(),一定要重写hashCode()。equals()相等的对象必须返回相同的hashCode()。Objects.hash()或IDE模板,以避免错误。hashCode()必须在对象的"生命周期"内返回相同的值(如果参与hashCode的字段是不可变的)。class User { private String name; public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; User user = (User) o; return Objects.equals(name, user.name); } public int hashCode() { return Objects.hash(name); } }
问题: "如果两个通过equals()不同的对象返回相同的hashCode(),这会是一个错误吗?"
答案: 不是,这是可以接受的。哈希冲突是可解决和可预期的——重要的是,如果对象在equals上相等,则它们的hashCode必须相同。如果不同的equals对象产生相同的hashCode,集合将变得更慢(由于更多的冲突),但仍然是正确的。
故事
在金融软件中,多个字段进行项目比较,但只重写了equals()。对象存储在HashSet中,出现了重复,因为hashCode()没有被重写且使用了默认(对于每个实例不同)。
故事
在仓库管理系统中,在添加业务逻辑更改后扩展了equals(),但忘记更新hashCode()。具有不同hashCode但equals=true的对象在HashMap中丢失(无法通过键找到),导致重大财务错误。
故事
在Web应用程序中在计算hashCode时使用了可变字段。更新内部字段的值时,哈希值发生变化,导致对象在HashSet/HashMap中“丢失”:无法通过标准方法找到或删除,导致内存泄漏和错误。