== and equals() and hashCode()

== and equals() and hashCode()

涉及两个主要内容

  • ==equals()方法的区别
  • equals()方法与hashCode()方法介绍

参考文章

== 与equals()的异同

相同点:都可以用来比较两个变量是否相等。

不同点

  1. equals()是方法method,==是操作符operator;

  2. equals()只能用于判断两个对象是否相等(即,只能用于判断引用数据类型的变量),不能用于判断基本数据类型的变量。

  3. == 既可以判断基本数据类型的变量,也可以用于引用数据类型

    1. 对于基本数据类型来说,==比较的是
    2. 对于引用数据类型来说,==比较的是对象的内存地址

    因为Java只有值传递(call by value,按值调用),所以对于==来说,不管是比较基本数据类型,还是引用数据类型,其本质都是比较值,只是引用数据类型的变量其值存的是对象的地址。

equals()

作用:用于判断其他对象是否与该对象相等。(判断两个对象是否相等。)

实现equals()方法时,需要满足JavaSE定义的如下约定:

以下约定针对所有的non-null reference value(非null的引用值)

  • 反身性 reflexive ,不为null的x,满足 x.equals(x)true
  • 对称性 symmetric,不为null的x,y,如果x.equals(y) 为true,那么y.equals(x)也应该为true。
  • 传递性 transitive,不为null的x,y,z,当x.equals(y)为true,y.equals(z)为true,那么x.equals(z)也应该为true。
  • 一致性 consistent ,对于不为null的x,y,只要它们对象的equals()方法没有修改,那么无论调用多少次x.equals(y),都应该始终返回true或者始终返回false。
  • 对于任何不会null的引用值x,x.equals(null) 应该返回false。

注意:使用equals()方法进行比较两个对象是否相等时,有两种使用情况:

  1. 类没有覆盖Object.java中的equals()方法,此时equals()方法等价于**==**,是比较对象的地址是否相等。

    1
    2
    3
    4
    // Object.java 中定义的equals()方法。当使用默认方法时,等价于 ==,比较对象的地址。
    public boolean equals(Object obj) {
    return (this == obj);
    }
  2. 类覆盖了Object.java中的equals()方法,此时我们一般使用equals()方法来判断两个对象的内容是否相等,这也是一般我们使用equals()的场景。

equals() & hashCode()的联系

  • 当不用在基于哈希表的集合数据类型中时,equals() 与 hashcode(),可以没有什么关联,此时hashCode不起作用。

  • 当用在基于哈希表的集合类型中时,equals()重写,则hashcode()一定要一起重写(原因下面写)。

什么后需要复写equals() 和 hashcode()?

请注意,每当重写此方法(equals)时,通常都需要重写 hashCode 方法,以维护 hashCode 方法的一般约定,即相等的对象必须具有相等的哈希码

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

JavaSE文档上 https://docs.oracle.com/javase/8/docs/api/

hashCode()

作用:返回对象的哈希码值。支持此方法是为了使用哈希表,例如 HashMap 提供的哈希表。

Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by HashMap.

hashCode的一般约定

  • 在 Java 应用程序执行期间(即在同一个JVM中),只要对象的 equals()方法中涉及的信息没有被修改,那么在同一个对象上无论调用hashCode方法多少次,hashCode 方法必须始终返回相同的整数。

    在不同的Java程序运行期间(即不同的JVM中),则不需要保持一致。

  • 如果根据 equals(Object) 方法两个对象相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果。

    简单的说就是,两个对象如果通过equals()相等,那么它们的hasCode值必须相等。

    相等的对象要有相等的hashCode。

  • 当根据equals(Object)方法判断两个对象不相等,那么不要求它们的hashCode必须唯一,但是从提升hashtable性能的角度考虑,不同的对象应该生成不同的hashCode。

    不同的对象,hashCode要尽量唯一。

    注:(如果对象不同但是hashCode相同,这就是hash冲突,会影响哈希表的性能)

hashCode使用场景

Hashcode值,主要用于基于散列的集合,如 HashMap、HashSet、HashTable…等

Hashcode value is mostly used in hash-based collections like HashMap, HashSet, HashTable….etc

HashMap和HashSet,当插入时,使用对象的hashCode值来决定对象插入时的存储在集合中的位置,当查找时,使用hashCode来帮助定位对象在集合中的位置。

Hash检索,涉及:

  1. firstly,使用hashCode()方法找出正确的bucket;
  2. secondly, 使用equals()在bucket中搜索正确的元素。

补充:哈希值/散列码(hash code)的作用

我们都知道,散列表(/哈希表)存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!
散列表的本质是通过数组实现的。当我们要获取散列表中的某个“值”时,实际上是要获取数组中的某个位置的元素。而数组的位置,就是通过“键”来获取的;更进一步说,数组的位置,是通过“键”对应的散列码计算得到的。

可以举例说明在hase-based collection中如果equals()与hashCode()不一起重写会带来哪些错误的影响

可以查看参考文章中的举例

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2022-2023 ligongzhao
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信