=============================================
原文链接: 为什么覆写equals必须要覆写hashCode? 转载请注明出处!
=============================================
《Effective java》Chapter Three Item 9:Always override hashCode when you overried equals. (下载链接: Effective_java(英文版)第二版.pdf )
1、 在Object中有两个方法:
public native int hashCode(); public boolean equals(Object obj) { return (this == obj);//默认比较引用相等 }
所以任何一个对象都有默认的hashCode()和equals()方法。
2、在hash表中,hashCode()方法是参与取/存值运算的。
例如:
//HashTabel if ((e.hash == hash) && e.key.equals(key)) { return (V)e.value; } //HashMap if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e;
由此可见,在根据key取value的时候,key相等的必要条件就是两者hashCode相等。
再说为什么覆写equals必须要覆写hashCode?注意:研究的对象是同一个类的两个不同对象(引用不同)
先看一段代码:
@Test public void testHashCode(){ Student stu1 = new Student("JACK"); Student stu2 = new Student("JACK"); System.out.println(stu1.equals(stu2));//equal返回true System.out.println(stu1.hashCode()+"----"+stu2.hashCode());//hashCode 结果不同。由于Student未覆写hashCode方法,在计算的时候使用的是的Object.hashCode(),计算出来两者的hashCode不一致 HashMap map = new HashMap(); map.put(stu1,"123456"); System.out.println(map.get(stu2));//(逻辑上)本想取出“123456”,但hashMap在取值的时候把两者的hashCode加入比较,因此找不到相等的key值,所以取出结果为null } class Student { private String name; public Student(String name){ this.name = name; } @Override public boolean equals(Object obj) { //逻辑上名字相等便认为两者相等并不是把引用相等作为判等条件 return this.name.equals(((Student)obj).name); } }
运行结果如下:
true 668849042----434176574
null
由这段代码可以看出:在执行map.get(stu2)的时候,程序会获取stu2的hashCode。而Student未覆写hashCode(),所以直接使用父类Object.hashCode()计算hash值,而由于Object.hashCode()返回的stu1和stu2的hash值并不相同,因此,map中未找到stu2对应的key值,所以返回的value便为null。
而示例程序中,本想根据名字相等来判断对象相等获取value值“123456”,可由于调用hashCode()的返回值不同导致最终未取得想要的值。那么解决办法是什么?让stu1.hashCode() == stu2.hashCode()。那么该如何实现? 自定义(覆写)hashCode()方法。
所以如果自定义了equals()方法,且返回true的充要条件不是(this == obj),那么就必须覆写hashCode,且必须保证equals为true的时候两者的hashCode必须相等,否则当该对象作为key值存在hash表中的时候,就无法用逻辑上相等的对象取出该key所对应的value(如示例)。
Object specification [JavaSE6]: • Whenever it is invoked on the same object more than once during an execution of an application, the hashCode method must consistently return the same integer, provided no information
used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application. • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. • It is not required that if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results.
However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
----end
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!