- 原始的equals是比较两个对象的地址,而hashCode也是由地址构造来的。
- 重写equals方法并改变其中比较的参数时,hashCode也应该改变。
- 如果根据equals方法,两个对象是一样的,那么它们的hashCode也应该一样。
- 如果两个对象不相等,hashCode不强制要求不一样,但是能不一样更好。
以下代码是一个手机号码的例子,手机号码由区号和本地手机号构成。我们重写了equals方法,但没有重写hashCode。
public class TantanitReaderPhone { private String areaCode; private String localNumber; public TantanitReaderPhone(String areaCode, String localNumber) { this.areaCode = areaCode; this.localNumber = localNumber; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TantanitReaderPhone that = (TantanitReaderPhone) o; //区号、号码都相同即为相同 return Objects.equals(areaCode, that.areaCode) && Objects.equals(localNumber, that.localNumber); } @Override public int hashCode() { return super.hashCode(); } }
以下测试代码定义了一个以TantanitReaderPhone为key的HashMap。我们在保存和取出时,分别都new了一个对象,这两个对象有着相同的areaCode和localNumber,根据我们重写的equals方法,它们是相等的。但是由于我们没有重写hashCode方法,导致get()时调用hashCode方法获取hashCode来定位时得到这两个对象的哈希值不同,所以第二个对象无法再HashMap里面找到第一次存进去的值。
Map<TantanitReaderPhone,String> map=new HashMap<>(); map.put(new TantanitReaderPhone("86","13200001234"),"张三"); //取不出来 map.get(new TantanitReaderPhone("86","13200001234"));
因此,hashCode方法应该包含equals中所有字段,而不能包含没有的字段,可能导致相等的对象有不同哈希值。比如,String的hashCode是根据每一个字符来构造的,而本例中的hashCode():
@Override public int hashCode() { int result=17; //若areaCode、localNumber两个字符串分别相同则返回hashCode相同 result=31*result+areaCode.hashCode(); result=31*result+localNumber.hashCode(); return result; }
高效Java技巧之重写hashCode方法
最后更新时间:
这里可以写作者留言,标签和 hexo 中所有变量及辅助函数等均可调用,示例:http://47.107.237.149/2019/04/30/高效Java技巧之重写hashCode方法/