Android技术知识半栈工程师Android知识

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

2018-05-24  本文已影响161人  闲庭

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

如果一个类没有自己定义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方法,但是不是重写了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()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!

上一篇 下一篇

猜你喜欢

热点阅读