为何覆写equals必需要覆写hashCode? 为何覆写equals必需要覆写hashCode?

=============================================html

原文连接: 为何覆写equals必需要覆写hashCode? 转载请注明出处!java

=============================================api

《Effective java》Chapter Three  Item 9:Always override hashCode when you overried equals. (下载连接: Effective_java(英文版)第二版.pdf oracle

 一、 在Object中有两个方法:app

public native int hashCode(); 
public boolean equals(Object obj) {
  return (this == obj);//默认比较引用相等
}

 因此任何一个对象都有默认的hashCode()和equals()方法。ide

 二、在hash表中,hashCode()方法是参与取/存值运算的。post

     例如: ui

//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相等。this

    再说为何覆写equals必需要覆写hashCode?注意:研究的对象是同一个类的两个不一样对象(引用不一样)url

   先看一段代码:

    @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:

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

相关文章
相关标签/搜索