• java中的equals与hashcode

    普通类
    • 支持
    • 批判
    • 提问
    • 解释
    • 补充
    • 删除
    • equals与hashcode

    例:两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

    不对,有相同的hash code。首先equals()hashcode()这两个方法都是从object类中继承过来的。

    equals()方法在object类中定义如下:

    public boolean equals(Object obj) {

    return (this == obj);

    }

    很明显是对两个对象的地址值进行的比较(即比较引用是否相同)。但是我们必需清楚,当String Math、还有IntegerDouble。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法。是进行的内容比较,而已经不再是地址的比较。依次类推DoubleIntegerMath。。。。等等这些类都是重写了equals()方法的,从而进行的是内容的比较。当然了基本类型是进行值的比较,这个没有什么好说的。

    我们还应该注意,Java语言对equals()的要求如下,这些要求是必须遵循的:

     对称性:如果x.equals(y)返回是“true,那么y.equals(x)也应该返回是“true

     反射性x.equals(x)必须返回是“true

     类推性:如果x.equals(y)返回是“true,而且y.equals(z)返回是“true,那么z.equals(x)也应该返回是“true

     还有一致性:如果x.equals(y)返回是“true,只要xy内容一直不变,不管你重复x.equals(y)多少次,返回都是“true

     任何情况下,x.equals(null),永远返回是“falsex.equals(x不同类型的对象)永远返回是“false

    以上这五点是重写equals()方法时,必须遵守的准则,如果违反会出现意想不到的结果,请大家一定要遵守。

    2. 其次是hashcode() 方法,在object类中定义如下:

    public native int hashCode();

    说明是一个本地方法,它的实现是根据本地机器相关的。当然我们可以在自己写的类中覆盖hashcode()方法,比如StringIntegerDouble。。。。等等这些类都是覆盖了hashcode()方法的。

    想要明白hashCode的作用,你必须要先知道Java中的集合。总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000equals方法。这显然会大大降低效率。于是,Java采用了哈希表的原理。hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。  

    3.这里我们首先要明白一个问题:

    equals()相等的两个对象,hashcode()一定相等;hashcode()不等,一定能推出equals()也不等hashcode()相等,equals()可能相等,也可能不等。

    【到这里你可能觉得equals()相等的两个对象,hascode()一定相等;hascode()相等的两个对象equals()一定相等。如果是没有重写Object类中的这两个方法,上述说法正确。但问题是,我们可以重写这两个方法,重写这两个方法又要遵循一定的规则:

    1、如果两个对象相同,那么它们的hashCode值一定要相同;

    2、如果两个对象的hashCode相同,它们并不一定相同   。

    之所以会有这样的规定,是为了某些操作的性能的考虑。比如向哈希表中插入元素。

    equals()方法会自动调用hashCode方法么?不会.除非你设计一个equals()方法 让它调用hashCode()方法. HashSet里的add()方法会通过一系列的调用使用到 hashCode()方法,因为它要根据hash值来确定存储位置,不是equals方法调用的.凡是用哈希表实现的集合先比较的是hashCode方法,这是为了程序性能的问题。

     当一个对象你只重写equals方法或hashCode方法,那么势必在一种情况下成立一种情况下不成立,所以只有2个方法同时改的情况下就会在各种情况下都出现你要的结果。我想这就是重写equals()方法必须重写hashCode方法的原因!

    hashcode()的函数,如果写成return 1;行不行。

    我说是可以的,只是性能很差,不停的冲突。看得出来这个回答还是让他很满意的。 hashCode()返回该对象的哈希码值,该值通常是一个由该对象的内部地址转换而来的整数,它的实现主要是为了提高哈希表(例如java.util.Hashtable提供的哈希表)的性能。哈希函数,解决冲突。

     equals()与“==

    "==" 比较的是两个对象的引用 (references),并不是他们的内容,(只是针对于对象类型,基本类型直接使用==或!=比较内容)

    Object 中的 equals(Object) 方法其标准形式为    public boolean equals(Object obj);返回类型为 boolean ,即 true/false  "==" 返回类型一样。Object 类中定义的 equals(Object) 方法是直接使用 "==" 比较的两个对象,所以在没有覆盖 (override,或称改写、重写) equals(Object) 方法的情况下,equals(Object)  "==" 一样是比较的引用

    equals(Object) 方法与 "==" 相比的特殊之处就在于它可以覆盖,所以我们可以通过覆盖的办法让它不是比较引用而是比较数据内容。当然 JDK 中也有覆盖过 equals(Object) 方法的类,如 java.lang.String,它就覆盖了从 Object 继承来的的 equals(Object) 方法,用以比较字符串内容是否相同。看看下面这个例子:

        public class Example1    {
        public static void main(String[] args){
        String s1=new String("abc");
        String s2=new String("abc");
        System.out.println("
     == 比较结果");
        System.out.println(s1==s2);
    //false
        System.out.println("
    equals(Object) 比较结果");
        System.out.println(s1.equals(s2));
    //true
        }
        }
        
    例中用 equals(Object) 比较结果为 true。用 == 比较结果为 falseString.equals(Object) 方法直接比较了两个字符串的内容,如果相同则返回 true ,否则返回 false

    由于和对象相关的变量属于引用类型,使用obj1obj2obj1只是得到一份obj2应用的副本,而不是obj2对象本身。

     

    • 标签:
    • 方法
    • 比较
    • 对象
    • equals
    • hashcode
    • 元素
    • true
    • 返回
    • object
    • 两个
  • 加入的知识群:
    学习元评论 (0条)

    评论为空
    聪明如你,不妨在这 发表你的看法与心得 ~



    登录之后可以发表学习元评论
      
暂无内容~~
顶部