`

为什么覆盖了equals()也必须覆盖hashcode()方法

 
阅读更多
    当我们重写了对象的equals方法,一般情况下(这里我指这些对象不需要放到Set或Map中仅仅是比较需要,或者虽然放到Set或Map中,但是get和set时用的是同一对象)是没有问题的,但是,有些情况下就不同了;举个例子:

public class Person(){
    private int id;
    private String name;
    //define getter and setter here, omited

     public void equals(Object obj){
         if (!(obj instanceof Person)){
              return false;
         }     
         return super.equals(obj) && ((Member) obj).getId() == this.getId();
    }
}


    上述class中没有覆盖hashCode方法,因此这个时候用的是Object.hashCode()的返回值;我们来测试一下。

public class TestHashCode extends TestCase {
    public void testMap() {
        Person p1 = new Person(1,"aaa"),p2 = new Person(1,"bbb");
        Map map = new HashMap();
        map.put(p1,p1);
        Member value = (Person)map.get(p2);
        System.out.println(value.getName());
    }
}


    请注意,这两个对象是相等的,可以从equals()的定义看出来;运行TestHashCode ,结果是NullPointerException;

     现在添加hashCode()到Person中。

public int hashCode() {
     return this.getId() * 37 ;
}


    重运行TestHashCode ;huh,我们想要的结果出现了,“aaa”

    为什么,老早的时候我就问过自己,只怪自己不求甚解;其实很简单Map.put(key,value)时根据key.hashCode生成一个内部hash值,根据这个hash值将对象存放在一个table中Map.get(key)会比较key.hashCode和equals方法,当且仅当这两者相等时,才能正确定位到table。

    回到先前的问题,为什么添加person.hashCode()前,得不到person对象;因为java中默认的hashCode是根据对象的地址计算得到的,虽然p1.equals(p2)=true,但是p1,p1有不同的内存地址,所以有不同的hashCode;所以通过p2是不能得到value的,这个时候value==null;添加hashCode()后,两个对象有相同hashCode,所以能得到。

    java中Set是通过Map实现的,所以Map和Set的所有实现类都要注意这一点。

    HashMap是通过链地址法解决hash collision的,并且新对象都是添加到表头的。






分享到:
评论

相关推荐

    hashcode和equals方法

    equals()和hashcode()这两个方法都是从object类中继承过来的。当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法.

    Java 覆盖equals时总要覆盖hashcode

    主要介绍了Java 覆盖equals时总要覆盖hashcode的相关资料,这里附有实例代码,具有参考价值,需要的朋友可以参考下

    java 序列化和重写 hashCode 的原因

    java 序列化和重写 hashCode 以及 equals 方法的例子

    jv-equals-hashcode

    jv-equals-hashcode 给定的类—矩形。 覆盖它的方法equals()和hashCode()所以equals()通过其字段(颜色,宽度和长度equals()比较Rectangle对象。 还要确保hashCode()遵循equals和hashcode之间的约定。

    commons-lang

    2.ObjectUtils 主要是对null进行安全处理,可以设置为null时的默认返回值,比较相等时是调用对象的equals方法,因此需要对对象进行方法进行覆盖 3.SystemUtils 主要获取一些系统属性,例如工作目录等等 4.DateUtils/...

    java面试常见问题(超详细).pdf

    Java中的equals方法和hashCode方法有什么关系? Java中什么是重载【Overloading】?什么是覆盖【Overriding】?它们有什么区别? Java中什么是多态?如何实现多态? Java中什么是接口?它有什么作用? Java中什么是...

    java集合知识-map、set等

    记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。 一般情况下,如果自定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,hashCode方法。 建立对象判断是否相同的依据。...

    Task_3-4-8_ComplexNumber

    覆盖其中的equals()和hashCode()方法,以便equals()通过re和im字段的内容比较ComplexNumber实例,并且hashCode()与equals()实现一致。 返回常数或未考虑re和im的小数部分的hashCode()的实现将不计算...

    java7源码-Java-for-Android-Interview-Outline:android-必填面试大纲欢迎Star,关注

    而开发中,我们往往不关心是否是同一块内存地址,我们关心的是两个对象的数据是否相同,所以官方建议:所有的Object子类,都应该重新覆盖equals方法. public int hashCode():返回一个hashCode值,hashCode值决定了该对象在...

    jdk 的集合框架的主体结构

    jdk 的集合框架的主体结构: Set 成员不能重复 HashSet 外部无序地遍历成员。 成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。

    安卓java读取网页源码-InterviewQuation:安卓面试的一些问题

    3)默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法, 而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象) 4)要是类中覆盖了equals方法,那么就要...

    Java入门教程(微学苑)-part1

    最好的最简单的Java入门教程。 目录 1 Java概述 1 1.1 Java语言概述 1 1.2 Java虚拟机以及跨平台原理 2 1.3 关于JVM的执行效率 2 1.4 客户端市场的折戟 3 ...4.22 hashCode() 方法 80 4.23 toString() 方法 80

    jdk-8u202-linux-x64.tar

    如果对应的索引处没有元素,直接存放,如果有对象在,那么比较它们的equals方法比较内容,如果内容一样,后一个value会将前一个value的值覆盖,如果不一样,在1.7的时候,后加的放在前面,形成一个链表,形成了碰撞...

    见面试官前,掏出来看看系列(三)之——JavaSE思维导图(持续更新中……)

    IO)容器Map面向对象技术重载和覆盖的区别面向对象的特征字符串和数组字符串创建与存储的机制”==“、equals()和hashCode有什么区别String、StringBuffer、StringBuilder和StringTokenizer的区别在java中的数组...

    sesvc.exe 阿萨德

    根据当前 key 的 hashcode 定位到具体的桶中并判断是否为空,为空表明没有 Hash 冲突就直接在当前位置创建一个新桶即可。 如果当前桶有值( Hash 冲突),那么就要比较当前桶中的 key、key 的 hashcode 与写入的 key...

    jdk-8u112-windows-x64.zip

    方法,计算出哈希码值,经过哈希算法算成数组的索引值,如果对应的索引处没有元素,直接存放,如果有对象在,那么比较它们的equals方法比较内容 如果内容一样,后一个value会将前一个value的值覆盖,如果不一样,在...

    jdk1.8.0_60_linux.zip

    方法,计算出哈希码值,经过哈希算法算成数组的索引值,如果对应的索引处没有元素,直接存放,如果有对象在,那么比较它们的equals方法比较内容 如果内容一样,后一个value会将前一个value的值覆盖,如果不一样,在...

    hibernate-types:Hibernate Types库为您提供了Hibernate ORM核心不支持的其他类型

    将JSON列类型映射到List或Map<String> ,需要确保POJO类型覆盖默认的equals和hashCode方法,并根据JSON对象的内容实现它们。 否则,Hibernate脏检查机制可能会触发意外的UPDATE语句。 查看。 Oracle 您应该使用...

    architect-awesome-code

    )因此,如果对象所属的类没有覆盖Object的hashCode(),指向同一对象的引用调用hashCode的值相等,而不同对象的引用的hashCode值是不可能相等的。HashSet不存入重复元素的规则是:hashCode()和equals()。元素的哈希...

Global site tag (gtag.js) - Google Analytics