简单解读equals()与“==”、hashcode()的关系

一、”==”和equals方法究竟有什么区别?

  • ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
    如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内 存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存(堆内存),此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存(堆内存)的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
  • equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
    String a=new String(“foo”);
    String b=new String(“foo”);
    两条new语句创建了两个对象,然后用a/b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值(对应对象的首地址)是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。

如果一个类没有自己定义equals方法(就比如之前创建的User类),那么它将继承Object类的equals方法,Object类的equals方法的实现源代码如下:

      public boolean equals(Object o) {
           return this == o;
       }

这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。

二、equals()与hashcode()

hashCode()方法和equals()方法的作用其实一样,在Java里都是用来对比两个对象是否相等一致,那么equals()既然已经能实现对比的功能了,为什么还要hashCode()呢?

因为重写的equals()里一般比较的比较全面比较复杂,这样效率就比较低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高,那么hashCode()既然效率这么高为什么还要equals()呢?

因为hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(hash冲突),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠,所以可以得出:

  • equals()相等的两个对象他们的hashCode()肯定相等,也就是用equals()对比是绝对可靠的
  • hashCode()相等的两个对象他们的equals()不一定相等,也就是hashCode()不是绝对可靠的

那是不是重写了equals()方法就一定要重写hashCode()方法呢?
一般来说涉及到对象之间的比较大小就需要重写equals方法,但是不是重写了equals就需要重写hashCode呢?实际上这只是一条规范,如果不这样做程序也可以执行,只不过会存在潜在bug。一般一个类的对象如果会存储在HashTable,HashSet,HashMap等散列存储结构中,那么重写equals后最好也重写hashCode,否则会导致存储数据的不唯一性(存储了两个equals相等的数据)。而如果确定不会存储在这些散列结构中,则可以不重写hashCode。但是个人觉得还是重写hashCode比较好一点,这样就不用考虑后期存储在哪些结构中,况且重写了hashCode也不会降低性能,因为在线性结构(如ArrayList)中是不会调用hashCode。

下面看一下一个对象放入散列集合的大致流程:

  1. 准备即将放入集合的对象
  2. 判断集合中是否存在hashCode值与这个对象相等的对象
    • 存在hashCode值相等的对象
      判断该对象和要放入对象的equals是否相等
      • 相等 –> 直接丢弃
      • 不相等 –> 存入集合
    • 不存在hashCode值相等的集合
      直接存入集合

所有对于需要大量并且快速的对比的话如果都用equals()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equals()去再对比了),如果hashCode()相同,此时再对比他们的equals(),如果equals()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!

    原文作者:闲庭CC
    原文地址: https://www.jianshu.com/p/b196d74f8aeb
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞