zoukankan      html  css  js  c++  java
  • 为什么要重写hashCode()和equals()方法

    1、剖析 equals()

    //Object类中的equals()
    public boolean equals(Object obj) {     
        return (this == obj);     
        } 

     equals()的定义为:

    public native int hashCode();

    是一个本地方法,返回的对象的地址值。

    内部是使用“==”比较引用是否指向同一个对象。所以在不覆盖equals方法时,使用equals方法和==的比较结果是一样的


    2、什么时候应该覆盖equals方法呢?

    当我们希望知道它们在逻辑上是否相等,而不是想知道它们是否指向同一个对象时,我们便需要覆盖equals方法了。

    覆盖equals方法的通用约定:

    1、自反性  对于任何非null的引用值,x.equals(x) == true

    2、对称性 对于任何非null的引用值x,y,x.equals(y) == y.equals(x)

    3、传递性  对于任何非null的引用值x,y,z,x.equals(y) ==true,y.equals(z)==true,------>x.equals(z)==true

    4、一致性 对于任何非null的引用值x,y,只要equals的比较操作在对象中所用的信息没有被改变,多次调用x.equals(y)返回的值不变。

    5、对于任何非null的引用值x,x.equals(null)必须返回false。

    实现equals()方法的小技巧:

    1,使用==操作符检查 参数是否为这个对象的引用,是则直接返回true。

    2,使用instance操作符检查 参数是否为正确的类型。

    3,把参数转换成正确的类型。

    4,对于该类中的每个关键域,检查参数中的域是否与该对象对应的域匹配。先比较最有可能不一致的域。

    5,覆盖equals方法时总要覆盖hashCode方法。

    6,不要将equals声明中的Object对象替换为其他对象。

    3、为什么覆盖equals方法时总要覆盖hashCode方法?

    因为如果不这么做的话,就违反了Object.hashCode的通用约定,导致该类无法结合所有基于散列的集合(HashMap,HashSet,HashTable)一起正常运作.

    在应用程序执行期间,只要equals方法的比较操作用到的信息没变,那么对这同一个对象调用多次,hashCode方法都必须始终如一的返回同一个整数.但在应用程序的多次执行中,即重新启动后结果可以不一致.
    如果两个对象根据equals比较是相等的,那这两个对象调用hashCode方法返回的结果必须是一样的.
    如果两个对象根据equals比较是不相等,那这两个对象调用hashCode方法返回的结果不一定不同.但不同的对象产生不同的hasCode,可以提高散列表的性能.
    不覆盖hashCode而违反的关键约定是第二条:相等的对象必须具有相等的hashCode.
    如果相同的对象具有不同的hashCode,那么将对象放入hashMap中,对象会被存放到不同的桶中,当去get 时,虽然是同一个对象,但是由于生成的hashCode不同,会到不同的桶中去找,此时便找不到那个对象

      4.hashcode()和equals()是在哪里被用到的?什么用的?

         HashMap是基于散列函数,以数组和链表的方式实现的。
    而对于每一个对象,通过其hashCode()方法可为其生成一个整形值(散列码),该整型值被处理后,将会作为数组下标,存放该对象所对应的Entry(存放该对象及其对应值)。

     equals()方法则是在HashMap中插入值或查询时会使用到。当HashMap中插入 值或查询值对应的散列码与数组中的散列码相等时,则会通过equals方法比较key值是否相等,所以想以自建对象作为HashMap的key,必须重写 该对象继承object的equals方法。

        
     5.本来不就有hashcode()和equals()了么?干嘛要重写,直接用原来的不行么?
         

          HashMap中,如果要比较key是否相等,要同时使用这两个函数!因为自定义的类的hashcode()方法继承于Object类,其hashcode码为默认的内存地 址,这样即便有相同含义的两个对象,比较也是不相等的,例如,

    Student st1 = new Student("wei","man");

    Student st2 = new Student("wei","man"); 

    正常理解这两个对象再存入到hashMap中应该是相等的,但如果你不重写 hashcode()方法的话,比较是其地址,不相等!

          HashMap中的比较key是这样的,先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若相等则认为他们是相等 的。若equals()不相等则认为他们不相等。如果只重写hashcode()不重写equals()方法,当比较equals()时只是看他们是否为 同一对象(即进行内存地址的比较),所以必定要两个方法一起重写。HashMap用来判断key是否相等的方法,其实是调用了HashSet判断加入元素 是否相等。

    由于在项目里经常会用到HashMap,所以在面试的时候基本会问这个问题。

    你有没有重写过hashCode方法?

    你在使用HashMap时有没有重写hashCode和equals方法?你是怎么写的?

    一个对象的hashcode可以改变么?

    如果大家要在HashMap的“键”部分存放自定义的对象,一定要在这个对象里用自己的equals和hashCode方法来覆盖Object里的同名方法。

  • 相关阅读:
    兼容ie10及以上css3加载进度动画
    MySQL的安装
    VSFTPD+MYSQL+PAM
    58.省市联动-json
    省市联动
    56.检验特殊字符
    55.全选2
    54.截取字符串的思想实现输入框字数限制
    网络截取文件名
    lastPathComponent的功能
  • 原文地址:https://www.cnblogs.com/xinghaonan/p/11933378.html
Copyright © 2011-2022 走看看