重写前

* ==表示两个对象的内存地址  * 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)都为重复项,就不会添加

  • 版权声明:文章来源于网络采集,版权归原创者所有,均已注明来源,如未注明可能来源未知,如有侵权请联系管理员删除。

发表回复

后才能评论