码迷,mamicode.com
首页 > 其他好文 > 详细

爱问面试题:==和equals()和Hashcode()三者的理解

时间:2020-03-15 23:54:54      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:rgs   return   为什么   hashset   main   哈希算法   添加   code   相等   

重写前

* ==表示两个对象的内存地址

* equals()也表示对象内存地址

*  hashCode()表示该对象在JVM中的32位内存地址

重写后:
==仍表示两个对象的内存地址
 equals()表示连个对象的值是否相等,相等就视为同一个对象
 如果equals()方法重写,那么hashCode()方法也要重写,因为要保证同一个对象的hashCode值相等这样的规定。

根据javaAPI文档上的介绍:

(1)、同一个对象的hashCode值一定相同,无论是否重写过equals()方法,也就是说重写过以后他们的值相等了,那么他们的hashCode也要保持相等,所以就也要重写hashCode()方法。

(2)、如果两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

比如重写后的hashCode方法如下:

@Override

?? ?public int hashCode() {
?? ??? ?final int prime = 31;
?? ??? ?int result = 1;
?? ??? ?result = prime * result + age;
?? ??? ?result = prime * result + ((name == null) ? 0 : name.hashCode());
?? ??? ?result = prime * result + sex;
?? ??? ?return result;
?? ?}

比较两个对象是否相等:

(1)先比较连个对象的hashCode值是否相等,如果相等则比较(2)(因为不同的对象也有可能hashCode值相等),如果不等则一定不是同一个对象

(2)再比较equals()方法,如果相等则视为同意对象,反之则不是同一个对象。**

2、hashCode()和equals()关系是什么?
明白几个原则:
equals相等的两个对象,hashcode一定相等。
equals不相等的两个对象,hashcode不一定不相等。
hashcode不相等,那么equals是一定不等的。
hashcode相等,equals可能相等,也可能不等

解释下第四个原则:
就好比hashcode像是一个词典目录里的按字母为索引查找字,查一个“Z”拼音开头的词,下面等查到“自己”,“自我”,“知道”等词,用equals就是判断这些词语当中是否有相等的词,“自己”和“知道”两个词不相等的,所以equals值不等,但它们同属于"Z"开头的词所以它们hashcode值相等。

3、为什么重写equals的同时也要重写hashCode呢?
hash算法是为了提高equals比较的效率而被发明出来的。这点在集合方面就能体现出来,就比如在List或Set集合里要比较是否有重复元素,当发现某个集合对象与另一个集合对象equals比较的结果相等时,则停止查找返回true值,反之,返回false值。
但如果集合中有大量元素呢,假设一个集合A里有10万元素,而且另一个比较的对象B中还可能没有重复的值,则意味着其实不用比较我都知道两者不相同,但程序依然会对集合A里遍历10万元素然后和B进行逐一排查。。。又或者当我要加入第100001个数据我要验证前面元素有重复值,就要跟前面10万个元素一一比较,效率可想而知很低。

哈希算法就是Java系统首先调用对象的hashCode()方法获得该对象的哈希码表,然后根据哈希码找到相应的存储区域,若哈希码相同在取得该存储区域内的每个元素与该对象进行equals方法比较,若不同也就没有继续比较的必要了,这对于数量较大的情况效率就提高了不少,重写hashcode方法,最主要就是保证操作的元素在同一个对象里且值都没有重复,若没有重写hashcode,可能会出现将对象引用不同,但元素完全相同的集合进行操作。

下面写一个例子

package demo;

public class override_HshCode_Equals {
public int x;
public int y;

public override_HshCode_Equals(int x, int y) {
    this.x = x;
    this.y = y;
}

@Override
public int hashCode() {
    //下面变量初始化值可以任意取
    final int prime = 31;
    int result = 1;
    result = prime * result + x;
    result = prime * result + y;
    return result;
}

/**
 * equals返回false就说明没有重复项可以添加
 * true是重复不能添加
 */
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;

    final override_HshCode_Equals heClass = (override_HshCode_Equals) obj;
    //这里就对实例化对象里的x,y进行比较
    if (x != heClass.x) {
        return false;
    }
    if (y != heClass.y) {
        return false;
    }
    return true;
}

}

测试类


package demo;

import java.util.HashSet;

public class TestMain {
    public static void main(String[] args) {
        HashSet<override_HshCode_Equals> set = new HashSet<override_HshCode_Equals>();
        override_HshCode_Equals heClass1 = new override_HshCode_Equals(1, 1);
        override_HshCode_Equals heClass2 = new override_HshCode_Equals(5, 5);
        override_HshCode_Equals heClass3 = new override_HshCode_Equals(1, 1);
        set.add(heClass1);
        set.add(heClass2);
        set.add(heClass3);
        set.add(heClass1);
        System.out.println("set数量=" + set.size());
    }
}
结果如下

set数量=2

注:重写override_HshCode_Equals类的hashCode相当于自定义返回了一个“哈希码”,对比x,y值是否相等,先比较hashcode值,heClass1(3,3)==heClass3(3,3),所以它们的hashcode值相等,但是heClass2的x,y和heClass1,heClass3的x,y值不等,所以hashcode不等,equals一定不等,所以heClass2对象是可以add进去的。前面说了heClass1和heClass3的hashcode值相等,然后进入equals进行对比,发现两者的对象都是相同的,根据程序add循序来看,所以heClass1是可以add进去的,然后heClass3和后面add(heClass1)都为重复项,就不会添加

爱问面试题:==和equals()和Hashcode()三者的理解

标签:rgs   return   为什么   hashset   main   哈希算法   添加   code   相等   

原文地址:https://blog.51cto.com/14232658/2478532

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!